本文同時(shí)發(fā)布至我的個(gè)人博客,點(diǎn)擊進(jìn)入我的個(gè)人博客閱讀。本博客供技術(shù)交流與經(jīng)驗(yàn)分享,可自由轉(zhuǎn)載。轉(zhuǎn)載請?jiān)谠u論區(qū)或私信簡單通知,感謝!
游戲簡介
? 射箭小游戲是一款射擊類小游戲,游戲規(guī)則十分簡單:玩家點(diǎn)擊屏幕上的任意位置,弓箭就會向著鼠標(biāo)所指的方向發(fā)射(注意弓箭會受到重力的影響)。玩家射中靶心得5分,每往外一環(huán)少一分,該游戲沒有輸贏設(shè)置。
游戲展示
?
設(shè)計(jì)思路
? 這次項(xiàng)目還是使用熟悉的MVC架構(gòu)。設(shè)計(jì)類圖如下所示:
開發(fā)過程
#### (一)構(gòu)建預(yù)設(shè)與素材
? 先準(zhǔn)備好游戲?qū)ο笕缂?、箭,設(shè)置的時(shí)候需要注意設(shè)置好Rigidbody屬性和Collider屬性。例如箭靶需要設(shè)置為is Kinematic避免它受到物理引擎的影響,而箭則需要設(shè)置is Kinematic為false并為其添加重力作用。至于Collider的設(shè)置,對于箭靶和箭頭的圓柱體我選擇了Mesh Collider,箭身則使用Capsule Collider,碰撞器的選擇會影響到物理效果的精度,對后面計(jì)分功能也有影響,需要謹(jǐn)慎選擇。另外,對于箭頭與箭身的結(jié)合,我使用了FixedJoint組件,這在后文會詳細(xì)介紹,在這里只要為箭頭與箭身添加該組件即可。
(二)代碼復(fù)用
? 在比較熟悉了MVC架構(gòu)之后,開發(fā)速率會極大提升,因?yàn)橹笆褂玫脑S多代碼其實(shí)是可以復(fù)用的。例如ScenceControl類與GameScenceController類,我直接復(fù)用了上次打飛碟項(xiàng)目的代碼,稍微修改一下類接口就可以立刻使用,開發(fā)效率得到很高的提升。對于ScenceControl類,我添加了一個(gè)setArrow()函數(shù),如下:
GameObject setArrow()
{
GameObject arrow = GameObject.Instantiate<GameObject>(arrowPrefab);
GameObject head = GameObject.Instantiate<GameObject>(headPrefab);
arrow.GetComponent<Rigidbody>().useGravity = false;
arrow.GetComponent<FixedJoint>().connectedBody = head.GetComponent<Rigidbody>();
head.GetComponent<FixedJoint>().connectedBody = arrow.GetComponent<Rigidbody>();
return arrow;
}
? 需要注意的是這里使用了FixedJoint組件,下面是該組件的簡介:
Fixed Joints restricts an object's movement to be dependent upon another object. This is somewhat similar to Parenting but is implemented through physics rather than Transform hierarchy. The best scenarios for using them are when you have objects that you want to easily break apart from each other, or connect two object's movement without parenting.
固定關(guān)節(jié)基于另一個(gè)物體來限制一個(gè)物體的運(yùn)動。效果類似于父子關(guān)系,但是不是通過層級變換,而是通過物理實(shí)現(xiàn)的。使用它的最佳情境是當(dāng)你有一些想要輕易分開的物體,或想讓兩個(gè)沒有父子關(guān)系的物體一起運(yùn)動。
? — Unity圣典
? 大致就是,Fixed Joints可以幫助我們實(shí)現(xiàn)兩個(gè)物體一同運(yùn)動的效果,需要注意的是這兩個(gè)物體必須都是剛體。在創(chuàng)建arrow與head后需要設(shè)置connectedBody屬性來實(shí)現(xiàn)綁定。
(三)通過射線實(shí)現(xiàn)射箭
? 這一部分代碼我們同樣熟悉了,與打飛碟中射出子彈的實(shí)現(xiàn)相似,這里不做贅述。代碼如下:
void FixedUpdate () {
if (Input.GetMouseButtonDown(0))
{
nowArrow = setArrow();
Vector3 mp = Input.mousePosition;
Ray ray = Camera.main.ScreenPointToRay(mp);
nowArrow.GetComponent<Rigidbody>().useGravity = true;
nowArrow.GetComponent<Rigidbody>().AddForce(ray.direction * 30, ForceMode.Impulse);
nowArrow.AddComponent<ArrowComponent>();
nowArrow = null;
}
}
? 這次的實(shí)現(xiàn)我將這部分代碼寫在FixedUpdate()而不是Update()中,這樣可以減少游戲消耗。
(四)碰撞的設(shè)置
? 通過OnTriggerEnter()可以監(jiān)測觸發(fā)器狀態(tài),當(dāng)碰撞發(fā)射時(shí)會自動調(diào)用該函數(shù),使用該函數(shù)我們可以實(shí)現(xiàn)“使箭留在箭靶” “計(jì)分”這兩個(gè)需求。如下:
public class ArrowComponent : MonoBehaviour {
private void OnTriggerEnter()
{
//取消動力學(xué)影響
this.GetComponent<Rigidbody>().isKinematic = true;
}
}
public class targetComponent : MonoBehaviour {
private void OnTriggerEnter()
{
//調(diào)用加分函數(shù)
GameScenceController.getGSController().addScore();
}
}
? 最后再添加UI,掛載腳本,游戲就基本完成了。