轉自:http://blog.ch-wind.com/ue4-event-dispatcher-and-delegate/設計模式
事件調度器很是的適合在各個藍圖之間實現通訊功能。app
當前UE4版本4.8.3。函數
在藍圖中,事件調度器的做用就像是事件的派發器。經過將事件預先的綁定在事件調度器上,可讓系統能夠在須要時將事件派發給全部已經綁定的事件。spa
一個比較常見的使用事件調度器的地方,就是關卡藍圖。翻譯
關卡藍圖中的不少物體的Actor及其邏輯,若是要脫離關卡藍圖的話會比較難於使用。所以,能夠經過將關卡藍圖中實現好的功能綁定到某個類,例如GameMode的事件調度器上來方便調度。設計
以下圖,在關卡藍圖的BeginPlay中將功能綁定到GameMode上:代理
而後能夠在GameMode的藍圖中,設定定時的調度關卡藍圖上的功能code
事件調度器同時支持解綁和解綁所有,以方便對事件調度的邏輯進行進一步的控制。blog
在C++和藍圖混合使用時,使用Blueprint Function Library能夠方便的實現藍圖到C++的調用。若是要實現C++對藍圖的邏輯的話,事件調度機制就很是的方便。seo
在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);
以後,就能夠在藍圖中向這個多播代理綁定事件來得到生成的數據了
事件調度器的機制在邏輯實現中很是的方便,尤爲是在關卡設計中,可能會比較常常用到。使用中也沒有遇到什麼特別須要注意的地方,邏輯很單純。