Unity 戰(zhàn)斗系統(tǒng)中角色UI血條設(shè)計(jì)
1:如何選取技術(shù)方案
Unity戰(zhàn)斗系統(tǒng)中,每個(gè)角色經(jīng)常會(huì)有血條與昵稱。如何架構(gòu)設(shè)計(jì)才高效,我們列舉一些常用的做法:
(1) onGUI來(lái)做昵稱與血條;
(2) 3D世界中創(chuàng)建一個(gè)3D物體來(lái)做血條與昵稱,然后讓血條與昵稱對(duì)著攝像機(jī);
(3) 基于UGUI/NGUI單獨(dú)做血條與昵稱的UI節(jié)點(diǎn),然后把UI節(jié)點(diǎn)位置與角色同步;
(4) 其它可能的做法;
方案(1)中onGUI的性能是很差的, 一般只用于顯示一些調(diào)試相關(guān)的信息,不適合用來(lái)做正式的游戲物體。方案(2)中創(chuàng)建3D物體,然后對(duì)著攝像機(jī),能實(shí)現(xiàn)功能,可能的問題就是血條昵稱這樣的物體,可能會(huì)打亂物體的合批,使得drawcall比較高, 昵稱與血條的Shader也可能與角色的不一樣,會(huì)有不斷切換Shader, set bass call爆增的風(fēng)險(xiǎn)。所以在正式的項(xiàng)目里面會(huì)使用方案(3)的UGUI/NGUI來(lái)單獨(dú)創(chuàng)建血條與昵稱的UI節(jié)點(diǎn),然后角色移動(dòng)同時(shí)更新同步UI節(jié)點(diǎn)的位置。
這樣角色到哪里血條與昵稱就跟到哪里。所有的血條與昵稱都在UGUI的一個(gè)節(jié)點(diǎn)下,大量角色戰(zhàn)斗的時(shí)候這些血條與昵稱可以合批一起繪制,盡量降低Drawcall。方案定下來(lái)后,就基于這個(gè)思路來(lái)實(shí)現(xiàn),需要解決角色與血條如何管理,角色與血條位置如何同步2大問題。

2: 如何排布角色節(jié)點(diǎn)與UI血條
3D角色美術(shù)建模完成以后,程序把它導(dǎo)入項(xiàng)目中,還要做一件很重要的事情,就是給這個(gè)角色加一個(gè)3D的節(jié)點(diǎn)mountPoint,這個(gè)節(jié)點(diǎn)在屏幕中的位置就是UI血條在屏幕中的位置,這個(gè)很關(guān)鍵。很多同學(xué)就會(huì)疑惑了,只要角色位置+一個(gè)固定的偏移就可以了,為什么要這個(gè)點(diǎn)呢?因?yàn)?D游戲與2D游戲不一樣,3D游戲物體在屏幕中的位置除了和自己本身有關(guān)系外還和攝像機(jī)的角度有關(guān)系,所以不能直接是位置加一個(gè)偏移,而是在3D角色上加一個(gè)合適的3D的點(diǎn),這個(gè)點(diǎn)在屏幕上的位置就是UI血條與昵稱所在的位置,如圖:

mountPoint的坐標(biāo)轉(zhuǎn)到屏幕坐標(biāo)后,就是UI血條與昵稱所在的屏幕位置。接下來(lái)看下UI節(jié)點(diǎn)。戰(zhàn)斗場(chǎng)景中都會(huì)有一個(gè)操作UI,所有的UI都要蓋在角色的血條與昵稱上,所以當(dāng)我們做戰(zhàn)斗場(chǎng)景的主UI的時(shí)候,專門做一個(gè)UIBloodRoot節(jié)點(diǎn),用來(lái)掛游戲中所有的血條與昵稱對(duì)象,如圖:

最后再做一個(gè)昵稱+血條的UI對(duì)象,等角色創(chuàng)建的時(shí)候,再把這個(gè)對(duì)象創(chuàng)建出來(lái),如圖:

3?戰(zhàn)斗系統(tǒng)中3D角色的UI代碼設(shè)計(jì)
首先每個(gè)戰(zhàn)斗單元,我們都會(huì)設(shè)計(jì)一個(gè)管理類提供策略,比如玩家對(duì)象,很多游戲會(huì)設(shè)計(jì)一個(gè)Player類來(lái)控制玩家, Boss怪會(huì)設(shè)計(jì)一個(gè)BossEnemy的類來(lái)控制Boss,而Player, Boss需要的很多策略,有些是共用的,血條就是其中之一,所以一般Player與Boss都會(huì)繼承自一個(gè)策略基類FightCharactor,我們就可以把戰(zhàn)斗掉血,吃道具加血以及UI血條的機(jī)制策略設(shè)計(jì)到FightCharactor里。
class FightCharactor extends Monobehaviour {
// 實(shí)現(xiàn)掉血,加血,血條的機(jī)制;
private float hp; // 戰(zhàn)斗單元的血量
private UICharactor uiCharactor; // 控制ui血條顯示,角色昵稱顯示的組件實(shí)例;
// end
public void Init() {} //
}
Class Player extends FightCharactor {
// 實(shí)現(xiàn)玩家特有的策略
// end
}
Class BossEnemy extends FightCharactor {
// 實(shí)現(xiàn)Boss特有的策略
// end
}
接下來(lái)設(shè)計(jì)一個(gè)UICharactor組件類,new 一個(gè)組件類的實(shí)例添加到血條與昵稱的ui對(duì)象上,來(lái)提供顯示血條進(jìn)度,與顯示角色昵稱的功能。
Class UICharactor extends MonoBehaviour {
public void SetBloodPer(float per) {…}
public void SetUnick(string unick) {…}
}
在主戰(zhàn)斗UI界面控制代碼處提供一個(gè)接口UICharactor CreateUICharactor(),返回UIChractor對(duì)象實(shí)例。偽代碼如下:
UICharactor CreateUICharactor() {
? ?GameObject uiObject = GameObject. Instantiate(UI血條+昵稱的預(yù)制體);
// 將血條對(duì)象放到UIBloodRoot節(jié)點(diǎn)下;
uiObject.transform.SetParent(this.UIBloodRoot, false);
UICharactor ctrl = uiObject.AddComponent<UICharactor>(); //添加組件實(shí)例到UI節(jié)點(diǎn)
return ctrl;
}
在戰(zhàn)斗角色FightCharactor類中的初始化方法Init中,調(diào)用UI控制代碼的CreateUICharactor接口,獲得UICharactor的組件實(shí)例,這樣就可以在戰(zhàn)斗掉血中,調(diào)用UICharactor的接口來(lái)顯示血量與昵稱了。
在代碼中this.uiCharactor. SetBloodPer接口可以顯示角色的血量,this.uiCharactor.SetUnick接口可以顯示玩家的昵稱等。
最后一件事情,就是角色到哪里,UI血條昵稱對(duì)象的位置就更新到哪里,這個(gè)如何設(shè)計(jì)呢?可以在FightCharactor類里面寫一個(gè)LateUpdate方法, 獲取戰(zhàn)斗單元中的mountPoint掛載點(diǎn)的位置, 然后將這個(gè)位置,結(jié)合游戲攝像機(jī)轉(zhuǎn)換為屏幕坐標(biāo), 然后在UICharactor代碼里編寫一個(gè)函數(shù)ShowAt(Vector3 screenPos);在UGUI里面把屏幕坐標(biāo)轉(zhuǎn)成ui節(jié)點(diǎn)的世界坐標(biāo),這樣UI血條昵稱節(jié)點(diǎn)位置就放到mountPoint對(duì)應(yīng)的屏幕點(diǎn)上了,玩家看起來(lái)就同步了。
class FightCharactor {
// …
void LateUpdate() {
Vector3 worldPos = this.mountPoint.transform.position;
Vector3 sceenPos = this.gameCamera.WorldToSceen(worldPos);
this.uiCharactor.ShowAt(sceenPos);
}
// …
}
class UICharactor {
// …
public void ShowAt(Vector3 sceenPos) {
Vector3 wordPos = ui模式下屏幕坐標(biāo)轉(zhuǎn)世界坐標(biāo);
this.transform.position = worldPos;
}
// …
}
本期的戰(zhàn)斗系統(tǒng)的UI血條昵稱的架構(gòu)與設(shè)計(jì)就分析到這里,我錄制了了一個(gè)視頻課件,完整的講解與實(shí)現(xiàn)了剛才的架構(gòu)與設(shè)計(jì),關(guān)注我可以領(lǐng)取。
附:戰(zhàn)斗系統(tǒng)的UI血條昵稱的架構(gòu)與設(shè)計(jì)視頻
https://www.bycwedu.com/promotion_channels/482597564