斯坦福UE4C++課程P23-P27UMG&玩家屬性
我們想把像血量、護(hù)甲、強(qiáng)壯度等玩家屬性加入到游戲中,最直觀的是放到角色類SCharacter中。這樣到最后,角色類可能包含成千上萬行代碼,維護(hù)起來很麻煩。
所以我們把這些放到Actor Component中,作為角色類的組件來使用。
我們新建一個SAttributeComponent類,作為角色的屬性類。
先了解下UPROPERTY宏的參數(shù)的意義:
在新建組件類中給健康值加上EditDefaultsOnly和BlueprintReadOnly。
組件cpp文件把健康值初始化為100,再寫一個修改生命值的功能
在角色類中添加上該組件,在藍(lán)圖編輯器中將看到該組件
接下來在魔法球C++類添加重疊事件觸發(fā)修改角色生命值函數(shù)。
現(xiàn)在魔法球打到角色身上,生命值都會減少20。

現(xiàn)在我們進(jìn)入UMG(Unreal Motion Graphics)部分。
內(nèi)容瀏覽器下創(chuàng)建UI-Widget Blueprint進(jìn)入到控件藍(lán)圖,在左邊除了可以添加默認(rèn)自帶的控件外,還可以直接添加之前我們做的十字準(zhǔn)星控件。
我們首先拖進(jìn)來一個文本框和進(jìn)度條(想要更好的進(jìn)度條可以用圖像、shader effect、材質(zhì))

接下來我們想要讓右側(cè)數(shù)字和角色生命值綁定,最常用的方式是屬性綁定,即點(diǎn)擊text控件右側(cè)create bind。本質(zhì)上是創(chuàng)建了一個每幀調(diào)用的函數(shù)。
創(chuàng)建之后來到函數(shù)編輯界面。為了便于了解函數(shù)功能(函數(shù)一多就不容易了解功能),我們把函數(shù)get text 0更名為GetHealthText。
現(xiàn)在我們沒有給返回值輸入任何東西,如果在角色類create widget和add to viewport之后,只會看到進(jìn)度條。

我們給返回值輸入99之后

可以看到99被顯示了出來

接下來要綁定角色屬性組件的生命值,可以這樣連

注意text是粉色線,字符串是粉紅線,兩者并不等價。
tip:UE4中的'string types'
FString:debug用的最多;允許字符串操作(append,split...)
FName:使用哈希映射,使得字符串比較更快;在系統(tǒng)和gameplay邏輯中用的多(eg. GetMuzzleLocation(FName));一經(jīng)賦值就不能被改變
FText:Front-end text to display in UI;Easily 'localized' into different languages
像之前我們在角色類查詢角色手骨骼位置的
就是使用FName來查詢“Muzzle_01”的。
現(xiàn)在效果如下:


之前的text綁定函數(shù)方法是每幀調(diào)用,效率比較低下,比較好的辦法是在血量改變時才改變該text值,這就好比別人只需告訴你一聲比你自己每幀都詢問效率高。
解決辦法是,這里在AttribureComponent類添加DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(DelegateName, Param1Type, Param1Name)宏。
注意:UE4宏參數(shù)有如下規(guī)則,類型和參數(shù)之間也要加逗號。
最后添加了4個參數(shù):
我們需要編寫委托事件FOnHealthChanged,當(dāng)其發(fā)生時,才進(jìn)行血量變化。
添加以下語句,assignable表示可以在藍(lán)圖中進(jìn)行綁定操作
再在cpp文件中把事件插入到合適的位置:
當(dāng)血量加上改變值delta之后,委托事件把Instigator、OwningComp、NewHealth、Delta進(jìn)行了填充。
現(xiàn)在編譯之后,打開角色藍(lán)圖,選中AttributeComp,可以看到右側(cè)細(xì)節(jié)的事件欄多了OnHealthChanged。

我們測試一下,當(dāng)血量改變時才打印血量值
點(diǎn)擊On Health Changed綠色+號,跳轉(zhuǎn)到藍(lán)圖,像如下連線


達(dá)到預(yù)期效果。
現(xiàn)在把功能從角色藍(lán)圖移到UI綁定函數(shù)中;
在PlayerHealth控件藍(lán)圖中,當(dāng)控件被構(gòu)造時,我們獲取到控件擁有者pawn類,轉(zhuǎn)換為C++SCharacter類,獲取到其中的AttributeComp組件,從該組件節(jié)點(diǎn)拖出藍(lán)線搜索assign On Health Changed,在事件分發(fā)器欄下選中目標(biāo)節(jié)點(diǎn),該節(jié)點(diǎn)將之前我們C++里寫的事件OnHealthChanged被綁定到目前的控件藍(lán)圖。每當(dāng)該事件發(fā)生時,我們設(shè)置進(jìn)度條也會改變(血量/100得到血量百分比,賦值給進(jìn)度條)

現(xiàn)在效果如下:

血量最大值我們是直接在藍(lán)圖里設(shè)置的100,不便維護(hù),所以我們使用在C++里定義的Health=100。在藍(lán)圖如下連:

GetClass獲取到事件擁有組件(角色attribute組件),然后GetClassDefaults獲取到該組件類所有屬性(我們只定義了Health,所以只顯示它)。
作者指出,他的學(xué)生經(jīng)常在角色藍(lán)圖創(chuàng)建控件后把控件提升為變量存儲下來,然后直接原地更新Health。因?yàn)槲覀兿M孶I去獲取角色的值,在UI邏輯里更改,而非在角色類去獲取UI改變其中的值,所以這種做法不推薦。
另外一點(diǎn),Pre Construct引腳拖出去執(zhí)行的邏輯會在該控件被添加到UI之前執(zhí)行,而Construct和BeginPlay一樣在游戲開始時才執(zhí)行。

我們可以在預(yù)構(gòu)造事件里設(shè)置進(jìn)度條顏色為紅色,編譯后進(jìn)度條在Designer里就是紅色;但在構(gòu)造事件里設(shè)置的話,在運(yùn)行游戲后進(jìn)度條才顯示為紅色。

接下來我們介紹控件藍(lán)圖中的動畫。原理是關(guān)鍵幀key frame。
我們可以在左下角新建一個Animation,命名為PulseHealthAnim,選中它之后,可以點(diǎn)擊右側(cè)details的參數(shù),為這些參數(shù)添加關(guān)鍵幀。
我們?yōu)槲谋驹O(shè)置3個關(guān)鍵幀,初始末尾scale為1,中間為1.2,按空格播放,效果如下:

現(xiàn)在在藍(lán)圖拖出該動畫,連在最后:

現(xiàn)在只要角色被擊中,就會播放該動畫。

最后我們讓玩家撞擊爆炸桶時會給玩家扣50血:
