UE4委託
委託的基本類型有三種:
- 單播委託
- 多播委託
- 動態委託
單播委託
單播委託指只能綁定一個函數指針的委託,也就是當執行委託時只能觸發一個唯一綁定的函數。
單播委託可以綁定一個無返回值或有返回值的函數。
//無返回值函數委託聲明
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;
應用場景總結
-
單播委託: 當我們只需要在C++中綁定和調用,且只有一個函數需要綁定委託時,可以使用單播委託。
當然,這個委託的綁定和調用可以通過二次函數調用暴露給藍圖。就是綁定和調用的函數再包裹一層,但一般沒有必要。 -
多播委託: 單播和多播最大不同就是多播可以綁定多個函數,且不能有返回值,其它功能與單播委託一樣。
-
動態委託: 顧名思義,就是允許動態綁定,它可以序列化,也就是說可以在藍圖中使用,下面再回顧一下應用場景。
我們可以將動態委託作爲變量,在函數中對委託調用,而委託的綁定可以在藍圖中進行。
下圖爲綁定委託,同時也是調用函數的參數。我們在DynDelTestFunc中對其調用。
典型案例就是SetTimerbyEvent藍圖結點,就是當時間截止時,調用綁定的委託。
-
動態多播委託: 這個更容易理解,它就是藍圖中的事件調度器(EventDispatcher),可以用其在C++和藍圖中綁定和調用委託。
事件
事件後續補充