1. 程式人生 > >Delegate in UnrealEngine ——虛幻四中的委託

Delegate in UnrealEngine ——虛幻四中的委託

@ CloudGuan
@ Copyright 2016 Cloud Guan, Inc. All Rights Reserved.

Delegates System In Unreal Engine

What is delegates in Unreal Engine?And How use it?

Delegates allow you to call member functions on C++ objects in a generic, yet type-safe way. Using delegates, you can dynamically bind to a member function of an arbitrary object, then call functions on the object, even if the caller does not know the object’s type.
代理機制允許你可以型別安全的使用C++類的成員函式,還可以自動的繫結成員函式到任意的變數上,然後通過這個變數來呼叫,我們這個變數甚至不需要知道它的型別。
It is perfectly safe to copy delegate objects. Delegates can be passed around by value but this is generally not recommended since they do have to allocate memory on the heap. You should always pass delegates by reference when possible.
拷貝代理變數是完全安全的,代理可以使用值傳遞,但是因為他們會在堆上分配記憶體的原因,所以不建議這樣做。最好是通過引用傳遞的方式來傳遞這個值
Both single-cast and multi-cast delegates are supported, as well as “dynamic” delegates which can be safely serialized to disk.
代理支援單播和廣播,自動的代理會更加的安全在序列化到磁碟的時候

Type of Delegate

這是可以用於普通型別和函式的代理,沒有特別要求使用UCALSS標記巨集標記的類,基本宣告方式如下表所示:

FuntionType Declear Delegate
void Function() DECLEAR_DELEGATE(Name)
void Fucntion(param1) DECLEAR_DELEGATE_OneParam(Name,paramType,paramType)
void Function(Param1,Param2,…) DECLARE_DELEGATE_Params( DelegateName, Param1Type, Param2Type, … )
RetVal Function() DECLARE_DELEGATE_RetVal( RetValType, DelegateName)

但是上面的巨集不能被藍圖使用,這個時候我們需要使用到新的一種代理,dynamic delegate同時宣告別的代理的巨集定義的方式如下
- DECLARE_MULTICAST_DELEGATE(DelegateName,ParamType,ParamName)
- DECLARE_DYNAMIC_DELEGATE
- DECLARE_MULTICAST_DYNAMIC_DELEGATE
注意這裡的宣告方式有點不同兩種代理方式,而且引數如果是自定義的類的話,也要被UNREALBUILDTOOLS的巨集進行標記,而且這裡不止要宣告引數型別和還要宣告引數名字

//另外這裡補充一個代理的高階用法,在代理引數不夠的時候,我們可以把額外的引數通過繫結代理的時候給傳遞進去

DCLEAR_DELEGATE(CloudGuanTextDelegate)

class CloudGuanText
{
public:
    static CloudGuanTextDelegate mydelegate;

    void cloudaguantext(FString Name);
};
//cpp
....
FString aaa=TEXT("aaaaaaa");
CloudGuanText cloudguan=new CloudGuanText();
cloudguan.mydelegate.BindRaw(this,&CloudGuanText::cloudaguantext,aaa);

Bind Delegates

函式 使用描述
Bind() Binds to an existing delegate object.繫結到現有的委託物件?
BindStatic 繫結原生的全域性C++函式的指標到一個Delegate
BindRaw() 繫結一個C++的指標到代理上,原生的指標沒有使用任何的智慧指標相關的特性,所以他是不安全的
BindSP() 繫結一個基於sharedPoint的成員函式代理,建議使用 ExecuteIfBound()呼叫
BindUOjecr 繫結一個基於UObject的成員函式到代理,UObject delegate持有到這個UObject的弱引用
UnBind() 解繫結

繫結代理是把這個代理需要執行的函式繫結到代理,當需要執行的實行呼叫Execute 或者ExecuteIfBound
下面是各個繫結方式的引數:

/**
     * Binds an arbitrary function that will be called to generate this attribute's value on demand.  After
     * binding, the attribute will no longer have a value that can be accessed directly, and instead the bound
     * function will always be called to generate the value.
     *
     * @param  InGetter  The delegate object with your function binding
     */
     //這裡的意思是我們需要傳遞的引數是一個代理的引用就好
    void Bind( const FGetter& InGetter )
    {
        bIsSet = true;
        Getter = InGetter;
    }
/**
* Binds a raw C++ pointer global function delegate
* 繫結的引數是一個函式的名字,這個函式要是是個全域性函式
*/
inline void BindStatic( typename FStaticDelegate::FFuncPtr InFunc )
{
    *this = CreateStatic( InFunc );
}

//這裡是繫結一個傳統c++類的指標,需要包含類的實列的指標以及成員函式,當然還有引數
inline void BindRaw( UserClass* InUserObject, typename TRawMethodDelegate_ThreeVars_Const< UserClass, PAYLOAD_TEMPLATE_LIST_ThreeVars >::FMethodPtr InFunc, PAYLOAD_TEMPLATE_ARGS_ThreeVars )
    {
        *this = CreateRaw( InUserObject, InFunc, PAYLOAD_TEMPLATE_PASSIN_ThreeVars );
    }
//繫結一個基於智慧指標的類的成員函式,同樣需要這個引數和類的例項的指標
inline void BindSP( UserClass* InUserObject, typename TSPMethodDelegate_ThreeVars_Const< UserClass, PAYLOAD_TEMPLATE_LIST_ThreeVars >::FMethodPtr InFunc, PAYLOAD_TEMPLATE_ARGS_ThreeVars )
    {
        *this = CreateSP( InUserObject, InFunc, PAYLOAD_TEMPLATE_PASSIN_ThreeVars );
    }
//繫結一個基於UObject的類的成員函式,需要的引數是這個類的例項的指標和函式指標
inline void BindUObject( UserClass* InUserObject, typename TUObjectMethodDelegate_FourVars_Const< UserClass, PAYLOAD_TEMPLATE_LIST_FourVars >::FMethodPtr InFunc, PAYLOAD_TEMPLATE_ARGS_FourVars )
    {
        *this = CreateUObject( InUserObject, InFunc, PAYLOAD_TEMPLATE_PASSIN_FourVars );
    }

這裡繫結引數形式是this,加上函式指標,原因是c++呼叫函式的原理,之後補充。