最近在做的游戲中經(jīng)常需要使用到定時器延遲贤惯。比如制作類似Moba游戲中的回城效果际跪,就會有一個幾秒鐘的延遲讀條宪睹。在標準的C/C++中我們可以用time庫函數(shù)比如Sleep來實現(xiàn)团搞,那么在Unreal中是怎么樣實現(xiàn)的呢绞旅?
1. C++
Unreal中有一個FTimerManager類專門實現(xiàn)與計時器相關(guān)的方法摆尝。官方的文檔可以看這里。其中我們發(fā)現(xiàn)了一個叫做SetTimer的函數(shù)因悲,這就是我們需要用的方法堕汞。
SetTimer函數(shù)有多個重載,常用的一個重載如下
SetTimer(FTimerHandle& InOutHandle, UserClass* InObj, typename FTimerDelegate::TUObjectMethodDelegate< UserClass >::FMethodPtr InTimerMethod, float InRate, bool InbLoop = false, float InFirstDelay = -1.f)
這幾個參數(shù)的意義如下
FTimerHandle & InOutHandle : 計時器的句柄
UserClass* InObj : 執(zhí)行此方法的類晃琳,一般為this
FTimerDelegate::TUObjectMethodDelegate< UserClass >::FMethodPtr InTimerMethod : 計數(shù)器每次結(jié)束后要執(zhí)行的代理函數(shù)
float InRate : 每次計時器的時間長度
bool InbLoop : 是否循環(huán)
float InFirstDelay : 循環(huán)計時器第一次迭代的時間讯检, 若小于0.f則使用inRate
我們基本上比較關(guān)注的參數(shù)是中間的3個琐鲁,代理函數(shù), 循環(huán)計時的長度人灼,以及是否循環(huán)围段。其中代理函數(shù)尤為重要,在回城的例子中投放,我們需要在延遲5秒鐘之后調(diào)用傳送的方法將玩家傳送到指定的地點(在Moba中為基地)奈泪。這里我們就需要把傳送的方法放在代理函數(shù)中實現(xiàn)。如果不需要切換關(guān)卡的話就是簡單的重新設(shè)置player Pawn的位置和旋轉(zhuǎn)灸芳。即SetActorLocation以及SetActorRotation涝桅。或者這使用bool TeleportTo(const FVector & DestLocation, const FRotator & DestRotation, bool bIsATest, bool bNoCheck)烙样。 兩者之間的差異請自行查閱資料冯遂,簡單來說就是Set方法能夠直接改變玩家的位置和旋轉(zhuǎn),而TeleportTo方法會優(yōu)先檢查目的地點能否使用误阻,如果可以才將玩家移動過去。
C++實現(xiàn)延遲的核心思想基本就是這樣晴埂。但是有時候我們也想要在界面上顯示一個類似LOL回城的倒計時讀條究反。這樣的話可以結(jié)合C++和藍圖來實現(xiàn)相關(guān)的UI。
2. 藍圖實現(xiàn)倒計時條
在藍圖中實現(xiàn)倒計時讀條的核心實際上是需要通過增加一個變量來記錄當(dāng)前已經(jīng)經(jīng)過的時間或者是還剩下的時間長度儒洛。其中倒計時后開始傳送這個部分可以采用之前的C++方式來實現(xiàn)精耐,當(dāng)然亦可以使用完全一樣的藍圖類實現(xiàn)。
在藍圖當(dāng)中SetTimer函數(shù)叫做Set Timer By Function Name琅锻,參數(shù)基本和C++的SetTimer一樣卦停。要注意的是,在Function Name這里我們需要自己創(chuàng)建一個自定義的事件恼蓬。名字完全和Function Name所定義的一樣惊完。
右鍵選擇Add Custom Event, 取和FunctionName中一樣的名字处硬,在本例中為Teleport小槐,將需要的邏輯實現(xiàn),這部分主要調(diào)用了傳送的函數(shù)來實現(xiàn)5秒鐘后回城荷辕。
接下來就是最關(guān)鍵的倒計時顯示功能凿跳。首先我們需要在UIWidget設(shè)計部分引入進度條ProgressBar和一個Text來動態(tài)顯示已經(jīng)等待時間。
在ProgressBar的Percent中設(shè)置為1疮方,并且增減綁定變量控嗜。
在左邊Variable欄定義一個新的float變量Countdown來記錄當(dāng)前經(jīng)過的時間。增加一個SetTimerByFunctionName節(jié)點骡显,設(shè)置為每0.1秒或者0.01秒(更加連貫)觸發(fā)疆栏。這個就用來更新進度條曾掂。
每隔0.01秒就會調(diào)用這個CountDown事件,將變量CountDown增加0.01承边,并且當(dāng)變量到達5之后遭殉,表明讀條已經(jīng)結(jié)束,我們自動地用Clear Timer By Function Name節(jié)點把計時器清空博助,CountDown復(fù)原為0险污,為下一次回城的時候再次使用做初始化準備。
致此富岳,回城倒計時的邏輯就已經(jīng)實現(xiàn)了蛔糯,我們需要的只是把它顯示在主界面上就可以了。我們之前分別給ProgressBar和Text綁定了兩個函數(shù)窖式。這兩個函數(shù)就是用來返回我們需要顯示的值蚁飒。
打開ProgressBar綁定的GetParent_0的藍圖界面,我們需要返回的是百分比的數(shù)值萝喘,所以將CountDown變量除以總讀條時間5秒返回淮逻。這樣進度條就會根據(jù)百分比刷新。
Text的顯示就更加簡單了阁簸,直接將CountDown由浮點型轉(zhuǎn)為Text輸出就完了爬早。我們的簡單的回城倒計時到此為止就完成了。Unreal的計時器還可以用來完成很多很有趣的功能启妹,計時器也是游戲中非常重要必不可少的一環(huán)筛严。