【UE4筆記】各種Delegate委託的區別和應用

UE4委託

委託的基本類型有三種:

  1. 單播委託
  2. 多播委託
  3. 動態委託

單播委託

單播委託指只能綁定一個函數指針的委託,也就是當執行委託時只能觸發一個唯一綁定的函數。
單播委託可以綁定一個無返回值或有返回值的函數。

//無返回值函數委託聲明
DECLARE_DELEGATE(DelegateName);			//無參
DECLARE_DELEGATE_OneParam(DelegateName, Param1Type);	//1個參數
DECLARE_DELEGATE_XXXParams(DelegateName, Param1Type, ...);	//多參
//有返回值函數委託聲明
DECLARE_DELEGATE_RetVal(RetValType, DelegateName);	//有返回值無參
DECLARE_DELEGATE_RetVal_OneParam(RetValType, DelegateName, Param1Type);	//有返回值,1個參數
DECLARE_DELEGATE_RetVal_XXXParams(RetValType, DelegateName, Param1Type, ...);	//有返回值,多參

聲明單播委託

DECLARE_DELEGATE(FTestDelegate);
class XXX_API AMyTestActor : public AActor
{
	GENERATED_BODY()
public:	
	AExecuteDelegateActor();
protected:
	virtual void BeginPlay() override;
public:	
	virtual void Tick(float DeltaTime) override;
public:
	//單播委託不能聲明BlueprintAssignable標識符。動態多播可以聲明BlueprintAssignable
	FTestDelegate TestDelegate;
}

將函數綁定到單播委託

函數 描述
BindSP 綁定SharedPtr指向對象的函數,即純C++類的函數。因爲純C++類一般會使用TSharedPtr用於管理內存。
BindThreadSafeSP 綁定線程安全的共享成員函數委託
BindRaw 純C++類變量,可以用其綁定委託
BindUFunction 如果成員函數有UFUNCTION宏表示,可用此綁定委託
BindUObject 綁定繼承UObject類的成員函數委託
BindStatic 綁定靜態(全局)函數委託,BindStatic(&MyClass::StaticFunc);
BindLambda 綁定一個Lambda函數
BindWeakLambda 綁定弱引用Lambda函數
UnBind 取消綁定委託
//綁定純C++類函數到委託
TSharedRef<FMyClass> MyClassObj(new FMyClass());
TestDelegate.BindSP(MyClassObj, &FMyClass::XXXFunc);

//綁定UObject子類函數到委託
TestDelegate.BindUObject(this, &UMyUObjectClass::XXXFunc);		//當前類內綁定
UMyUObjectClass* MyUObjectClassObj;								//其它類內綁定
TestDelegate.BindUObject(MyUObjectClassObj, &UMyUObjectClass::XXXFunc);

委託調用

函數 說明
IsBound 檢查是否綁定一個委託
Execute 不檢查綁定而執行委託
ExecuteIfBound 當綁定一個委託時,執行調用

多播委託

多播委託可以綁定多個函數,但不能有返回值。
事件是特殊類型的多播委託,它在訪問Broadcast()、IsBound()、Celar()函數時受限。

//多播委託
DECLARE_MULTICAST_DELEGATE(DelegateName);
DECLARE_MULTICAST_DELEGATE_ONEPARAM(DelegateName, Param1Type);
DECLARE_MULTICAST_DELEGATE_XXXPARAMS(DelegateName, Param1Type,...);

//動態多播委託
DECLARE_DYNAMIC_MULTICAST_DELEGATE(DelegateName);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ONEPARAM(DelegateName, Param1Type, Param1Name);
...

綁定多播委託

函數 說明
Add() 綁定類型參見單播委託,不同之處就是可以綁定多個函數
AddStatic()
AddRaw()
AddSP()
AddUObject()
Remove()
RemoveAll()

多播執行

Broadcast調用後,會執行所有綁定的委託,但是委託的執行順序尚未定義。

函數 說明
Broadcast() 執行所有綁定的委託

動態委託

動態委託可以序列化,其函數可以按命名查找,但執行速度比常規委託慢。

動態及動態多播委託的聲明宏結尾必須要有分號,所以建議給所有委託都加分號,這樣可以統一樣式。

//動態委託
DECLARE_DYNAMIC_DELEGATE(DelegateName);
DECLARE_DYNAMIC_DELEGATE_ONEPARAM(DelegateName, Param1Type);
DECLARE_DYNAMIC_DELEGATE_XXXPARAMS(DelegateName, Param1Type,...);

//動態多播委託,可以暴露給藍圖的委託時動態多播委託
DECLARE_DYNAMIC_MULTICAST_DELEGATE(DelegateName);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ONEPARAM(DelegateName, Param1Type, Param1Name);

動態委託變量(屬性)可以作爲函數的參數,當我們在藍圖調用函數的同時,可以綁定一個委託了。

DECLARE_DYNAMIC_DELEGATE(FMyDynamicDelegate);

public:
	//不能聲明爲藍圖實現函數,cpp文件必須有實現
	UFUNCTION(BlueprintCallable)
	void DynDelTestFunc(FMyDynamicDelegate MyDynamicDelegate)
	{	//這裏爲方便說明,直接在聲明處定義
		//調用出入的動態委託
		MyDynamicDelegate.ExecuteIfBound();
	}
	
public:
	FMyDynamicDelegate MyDynamicDelegate;

如下圖爲調用允許綁定動態委託的函數,這就是上面代碼的成果:
調用允許綁定動態委託的函數

綁定動態委託

函數 說明
BindDynamic(UserObject, FuncName) 用於在動態委託上調用BindDynamic()的輔助宏。自動生成函數命名字符串。
AddDynamic(UserObject, FuncName)
RemoveDynamic(UserObject, FuncName)

執行動態委託

函數 說明
IsBound() 用法與單播委託相同,見單播委託
Execute()
ExecuteIfBound()

動態多播委託

動態多播委託可以暴露給藍圖使用,並且聲明宏中不僅包含變量類型,也包含變量名。如果暴露給藍圖,需要給委託變量的UPROPERTY宏添加BlueprintAssignable標識符

DECLARE_DYNAMIC_MULTICAST_DELEGATE(DelegateName);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ONEPARAM(DelegateName, Param1Type, Param1Name);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_XXXPARAM(DelegateName, Param1Type, Param1Name,...);

委託聲明示例:

DECLARE_DYNAMIC_MULTICAST_DELEGATE_ONEPARAM(FDelegateTest, class AActor*, MyActor);

UPROPERTY(BlueprintAssignable)
FDelegateTest TestDelegate;

應用場景總結

  1. 單播委託: 當我們只需要在C++中綁定和調用,且只有一個函數需要綁定委託時,可以使用單播委託。
    當然,這個委託的綁定和調用可以通過二次函數調用暴露給藍圖。就是綁定和調用的函數再包裹一層,但一般沒有必要。

  2. 多播委託: 單播和多播最大不同就是多播可以綁定多個函數,且不能有返回值,其它功能與單播委託一樣。

  3. 動態委託: 顧名思義,就是允許動態綁定,它可以序列化,也就是說可以在藍圖中使用,下面再回顧一下應用場景。
    我們可以將動態委託作爲變量,在函數中對委託調用,而委託的綁定可以在藍圖中進行。
    下圖爲綁定委託,同時也是調用函數的參數。我們在DynDelTestFunc中對其調用。
    綁定委託
    典型案例就是SetTimerbyEvent藍圖結點,就是當時間截止時,調用綁定的委託。
    SetTimerbyEvent

  4. 動態多播委託: 這個更容易理解,它就是藍圖中的事件調度器(EventDispatcher),可以用其在C++和藍圖中綁定和調用委託。

事件

事件後續補充

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章