天天看點

【UE4 C++】代理(委托)單點傳播代理多點傳播代理動态代理動态代理用于藍圖

這裡寫目錄标題

  • 單點傳播代理
    • 聲明代理
    • 常用綁定函數的使用
      • 綁定UObject類型對象的成員函數的代理
      • 綁定基于共享引用的成員函數的代理
      • 綁定原始自定義對象成員函數的代理(執行需要檢查IsBound)
      • 綁定全局函數成為代理
      • 解除綁定代理關系
  • 多點傳播代理
    • 常用綁定函數的使用
  • 動态代理
    • 聲明動态委托
    • 動态委托綁定
    • 執行動态委托
  • 動态代理用于藍圖

單點傳播代理

聲明代理

聲明宏 描述
DECLARE_DELEGATE(DelegateTypeName); 聲明無函數參數類型,無函數傳回值的單點傳播代理DelegateTypeName
DECLARE_DELEGATE_OneParam(DelegateTypeName, Param1Type); 聲明包含一個函數參數類型,無函數傳回值的單點傳播代理DelegateTypeName
DECLARE_DELEGATE_ N u m Num NumParams(DelegateTypeName, Param1Type, Param2Type, …); 聲明包含 N u m Num Num個函數參數類型,無函數傳回值的單點傳播代理DelegateTypeName ( T w o < = N u m < = N i n e ) (Two <= Num <= Nine) (Two<=Num<=Nine)
DECLARE_DELEGATE_RetVal(RetValType, DelegateTypeName); 聲明無函數參數類型,有函數傳回值的單點傳播代理DelegateTypeName
DECLARE_DELEGATE_RetVal_OneParam(ReturnValueType, DelegateName, Param1Type); 聲明包含一個函數參數類型,有函數傳回值的單點傳播代理DelegateTypeName
DECLARE_DELEGATE_RetVal_ N u m Num NumParam(RetValType, DelegateTypeName, Param1Type, Param2Type, …); 聲明包含 N u m Num Num個函數參數類型,有函數傳回值的單點傳播代理DelegateTypeName ( T w o < = N u m < = N i n e ) (Two <= Num <= Nine) (Two<=Num<=Nine)

static DelegateTypeName DelegateName; // 聲明代理

常用綁定函數的使用

  • 綁定UObject類型對象的成員函數的代理

BindUObject(const UserClass* InUserObject, typename TMemFunPtrType<true, UserClass, RetValType (ParamTypes..., VarTypes...)>::Type InFunc, VarTypes... Vars)

使用一個有一個函數參數并且有傳回值的代理作為例子:

首先先要到一個類檔案中聲明代理,建立代理的一些邏輯:

DECLARE_DELEGATE_RetVal_OneParam(int32, DelegateTypeName, FString);

protected:
	DelegateTypeName DelegateName;
           

我這裡是測試,是以就将邏輯實作放在了

BeginPlay

函數中:

DelegateName.BindUObject(TestActor, &ATestActor::DelegateTestFunction);

if (DelegateName.IsBound())
{
    // ReSharper disable once CppExpressionWithoutSideEffects
    int32 Result = DelegateName.Execute(TEXT("123!"));

    UE_LOG(LogTemp, Warning, TEXT("傳回值為: %d"), Result);
}
           

使用

BindUObject

綁定一個函數,這個函數類型的傳回值以及參數類型一定要和代理的函數類型及傳回值一模一樣。

使用

Execute

執行這個函數,并用

Result

儲存傳回回來的值。

Result

進行列印測試結果是否成功。

結果:

【UE4 C++】代理(委托)單點傳播代理多點傳播代理動态代理動态代理用于藍圖

後面幾個函數現在不太懂怎麼去用,就整理一下有什麼作用分享給大家~

(後面懂了就來補,一定會補的,因為這是我的學習筆記,當用到這個知識點的時候我就會來看這篇文章,然後對他進行一個修改和整理。)

  • 綁定基于共享引用的成員函數的代理

if(!RawObjectPtr.IsValid())
{
	RawObjectPtr = MakeShareable(new RawObject);
	DelegateName.BindSP(RawObjectPtr.ToSharedRef(), &RawObject::DelegateTest); //将智能指針轉為智能引用
}
           
  • 綁定原始自定義對象成員函數的代理(執行需要檢查IsBound)

    隻能綁定到C++原生指針指向的方法(原生指針需要自己管理其記憶體的配置設定和釋放,而智能指針則會由系統自行管理其生命周期和垃圾回收);一般隻要在類中繼承了Unreal的UObject或其子類(Actor等),這個類就會是Unreal的類,其方法就不再是C++原生類的方法,就不能使用BindRaw();
if (!RawObjectPtr.IsValid())
{
	RawObjectPtr = MakeShareable(new RawObject);  //使用指針封裝,防止不能釋放
	DelegateName.BindRaw(RawObjectPtr.Get(), &RawObject::DelegateTest); //RawObject是自定義的原生類
}
           
  • 綁定全局函數成為代理

這個相對來說比較簡單,就小标題名字意思。

DelegateName.BindStatic(&MyClass::StaticMethod);

  • 解除綁定代理關系

DelegateName.Unbind();

多點傳播代理

聲明宏 描述
DECLARE_MULTICAST_DELEGATE( DelegateTypeName ); 聲明無函數參數類型,無函數傳回值的多點傳播代理DelegateTypeName
DECLARE_MULTICAST_DELEGATE_OneParam( DelegateTypeName, Param1Type ); 聲明包含一個函數參數類型,無函數傳回值的多點傳播代理DelegateTypeName
DECLARE_MULTICAST_DELEGATE_ N u m Num NumParams(DelegateTypeName, Param1Type, Param2Type, …); 聲明包含 N u m Num Num個函數參數類型,無函數傳回值的多點傳播代理DelegateTypeName ( T w o < = N u m < = N i n e ) (Two <= Num <= Nine) (Two<=Num<=Nine)

注意:多點傳播委托中函數簽名不能使用傳回值。

常用綁定函數的使用

函數 描述
Add() 将函數委托添加到多點傳播委托的調用清單中;
AddStatic() 添加原始C++指針全局函數委托;
AddRaw() 添加原始C++指針委托;
AddSP() 添加基于共享指針的成員函數委托,共享指針委托保留對對象的弱引用;
AddUObject() 添加基于UObject的成員函數委托,UObject委托保留對對象的弱引用;
Remove() 從該多點傳播委托的調用清單中删除函數(委托的順序可能不會被保留);
RemoveAll() 從該多點傳播委托的調用清單中删除綁定到直到UserObject的所有函數(委托的順序可能不會被保留)。

廣播:

調用Broadcast,但是調用不保證執行順序的正确性。

動态代理

聲明動态委托

代碼形式上是和普通代理差不多的,就是多了一個

_DYNAMIC

DECLARE_DYNAMIC_DELEGATE[_RetVal, …]( FDelegateTypeName )  // 建立一個動态委托

DECLARE_DYNAMIC_MULTICAST_DELEGATE[_RetVal, …]( FDelegateTypeName ) //建立一個動态多點傳播委托
           

太多了,而且寫到這上面也意義不大,講一下他的注意點吧。

注意:

  1. 代理名前需要添加一個 F F F)。
  2. 動态代理在類型後面必須加參數名稱。

    DECLARE_DYNAMIC_DELEGATE_RetVal_OneParam(int32, FDelegateTypeName, FString, Name);

  3. 動态代理綁定的函數,一定要聲明

    UFUNCTION()

    ,因為需要跟随代理被序列化(其他代理均不能使用)。

單點傳播無法在藍圖中綁定,無法使用宏

BlueprintAssignable

UPROPERTY

中的修飾符,僅能用于Multicast代理。應顯示該屬性,以供在藍圖中配置設定)修飾。

動态委托綁定

輔助宏 說明
BindDynamic( UserObject, FuncName ) 用于在動态委托上調用BindDynamic()的輔助宏。自動生成函數命名字元串。
AddDynamic( UserObject, FuncName ) 用于在動态多點傳播委托上調用AddDynamic()的輔助宏。自動生成函數命名字元串。
RemoveDynamic( UserObject, FuncName ) 用于在動态多點傳播委托上調用RemoveDynamic()的輔助宏。自動生成函數命名字元串。

和之前差不多的用法。

執行動态委托

執行函數 描述
Execute 不檢查其綁定情況即執行一個委托
ExecuteIfBound 檢查一個委托是否已綁定,如是,則調用Execute
IsBound 檢查一個委托是否已綁定,經常出現在包含 Execute 調用的代碼前

還有其他的函數就是單點傳播和多點傳播各自使用的那些函數了。

動态代理用于藍圖

例:

這個和之前一樣現在一個類中聲明動态委托:

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDynDelMul, FString, Name);
UPROPERTY(BlueprintAssignable, BlueprintReadWrite)
FDynDelMul DynDel;

UFUNCTION(BlueprintCallable) // 觸發結束開關,輸出結束内容
void EndTrigger();
           

在BeginPlay中綁定和廣播。

DynDel.AddDynamic(TestActor, &ATestActor::Function);

if (DynDel.IsBound())
{
	DynDel.Broadcast("DynDel");
}
           

EndTrigger内容:

if (DynDel.IsBound())
{
	DynDel.Broadcast("DynDel");
}
           

TestActor類的函數聲明:

UFUNCTION()
	void Function(FString Name);
           

函數定義:

void ATestActor::Function(FString Name)
{
	UE_LOG(LogTemp, Warning, TEXT("輸入字元串為: %s"), *Name);
}
           

建立有動态委托類的藍圖子類

在藍圖中可以使用:

【UE4 C++】代理(委托)單點傳播代理多點傳播代理動态代理動态代理用于藍圖

現在我們可以在藍圖上面進行我們的操作:

建立一個繼承ATestActor的藍圖類。

【UE4 C++】代理(委托)單點傳播代理多點傳播代理動态代理動态代理用于藍圖
【UE4 C++】代理(委托)單點傳播代理多點傳播代理動态代理動态代理用于藍圖

運作檢視輸出日志:

【UE4 C++】代理(委托)單點傳播代理多點傳播代理動态代理動态代理用于藍圖

繼續閱讀