轉自:http://blog.ch-wind.com/ue4-event-dispatcher-and-delegate/
事件調度器非常的適合在各個藍圖之間實現通信功能。
當前UE4版本4.8.3。
在藍圖中,事件調度器的作用就像是事件的派發器。通過將事件預先的綁定在事件調度器上,可以讓系統可以在需要時將事件派發給所有已經綁定的事件。
事件調度器的使用
一個比較常見的使用事件調度器的地方,就是關卡藍圖。
關卡藍圖中的很多物體的Actor及其邏輯,如果要脫離關卡藍圖的話會比較難於使用。因此,可以通過將關卡藍圖中實現好的功能綁定到某個類,例如GameMode的事件調度器上來方便調度。
如下圖,在關卡藍圖的BeginPlay中將功能綁定到GameMode上:
然后可以在GameMode的藍圖中,設定定時的調度關卡藍圖上的功能
事件調度器同時支持解綁和解綁全部,以方便對事件調度的邏輯進行進一步的控制。
Delegate
在C++和藍圖混合使用時,使用Blueprint Function Library可以方便的實現藍圖到C++的調用。如果要實現C++對藍圖的邏輯的話,事件調度機制就非常的方便。
在C++中,與事件調度器對應的是Delegate機制。事實上,Delegate機制的涵蓋范圍比事件調度器要大一些。
Delegate機制是一種常見的設計模式,相信做程序的童鞋都比較熟悉。這里不做多余的說明了。
UE4官方對Delegate的翻譯名稱唯代理。按照類型,分為單播代理和多播代理。其中,多播代理與事件調度器的功能類似,而單播代理更接近單純的代理,也就是只能綁定一個執行函數。
要讓多播代理像是事件調度器一樣使用的話,需要將其定義為Dynamic。對於單播代理也是一樣的。
在C++中使用UE4的代理功能,需要使用官方提供的宏進行定義。
函數簽名 | 聲明宏 |
void Function() | DECLARE_DELEGATE( DelegateName ) |
void Function( <Param1> ) | DECLARE_DELEGATE_OneParam( DelegateName, Param1Type ) |
void Function( <Param1>, <Param2> ) | DECLARE_DELEGATE_TwoParams( DelegateName, Param1Type, Param2Type ) |
void Function( <Param1>, <Param2>, … ) | DECLARE_DELEGATE_<Num>Params( DelegateName, Param1Type, Param2Type, … ) |
<RetVal> Function() | DECLARE_DELEGATE_RetVal( RetValType, DelegateName ) |
<RetVal> Function( <Param1> ) | DECLARE_DELEGATE_RetVal_OneParam( RetValType, DelegateName, Param1Type ) |
<RetVal> Function( <Param1>, <Param2> ) | DECLARE_DELEGATE_RetVal_TwoParams( RetValType, DelegateName, Param1Type, Param2Type ) |
<RetVal> Function( <Param1>, <Param2>, … ) | DECLARE_DELEGATE_RetVal_<Num>Params( RetValType, DelegateName, Param1Type, Param2Type, … ) |
針對不同的代理類型,使用不同的宏前綴即可:
多播代理 | DECLARE_MULTICAST_DELEGATE… |
動態單播代理 | DECLARE_DYNAMIC_DELEGATE… |
動態多播代理 | DECLARE_DYNAMIC_MULTICAST_DELEGATE… |
實際使用時,首先要對代理類型進行定義
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FDspLRValDelegate, float, LVals, float, RVals);
然后在具體的類,例如GameState中進行具體的聲明
UPROPERTY(BlueprintAssignable, Category = "SoundFuncs") FDspLRValDelegate DspLRVals;
這樣一來,就可以在需要調用這個代理的地方進行調用了,例如在某個數據生成的地方。
AMyGameState* tags = Cast<AMyGameState>(SL_Contex.LC_cGameState); if (tags) tags->DspLRVals.Broadcast(tfLval, tfRval);
之后,就可以在藍圖中向這個多播代理綁定事件來獲得生成的數據了
總結
事件調度器的機制在邏輯實現中非常的方便,尤其是在關卡設計中,可能會比較經常用到。使用中也沒有遇到什么特別需要注意的地方,邏輯很單純。