UE4的delegate

来源:互联网 发布:淄博seo推广优化 编辑:程序博客网 时间:2024/06/10 02:58


首先,UE4中的delegate和C#里边是一样的,delegate的本质是一个特殊类的对象,它可以储存(一个或多个)函数指针和payload数据(就是除了函数指针,还能存些你调用时候的额外参数)UE4中的delegate类名字中都有signature,这里我们以overlap的回调委托为例:在各种mesh components中,都有这么一个字段

FComponentBeginOverlapSignature OnComponentBeginOverlap;

其中FComponentBeginOverlapSignature这个类就是一个delegate,在这里,他还是一个broadcast delegate,我们看看他的实现

DECLARE_DYNAMIC_MULTICAST_DELEGATE_FiveParams( FComponentBeginOverlapSignature,class AActor*, OtherActor, class UPrimitiveComponent*, OtherComp, int32, OtherBodyIndex, bool, bFromSweep, const FHitResult &, SweepResult);

很显然,这个类的声明使用了UE4的一个宏定义,这个宏是一个系列,是专门用来声明delegate的,毕竟我们不可能自己声明一个delegate类,这太困难。但是使用这个宏,我们可以很方便的声明委托类。首先宏本体有很多种,看例子很好理解

DECLARE_DELEGATE( DelegateName )
声明一个叫DelegateName的类,他是一个返回void的没有参数的委托
DECLARE_DELEGATE_TwoParams( DelegateName, Param1Type, Param2Type ) 
返回void的名为DelegateName的两个参数的委托
DECLARE_DELEGATE_RetVal_OneParam( RetValType, DelegateName, Param1Type )
返回值为RetValType类型,有一个参数,类型为Param1Type

至于多播 (broadcast)和动态(dynamic),都有对应的声明

•DECLARE_MULTICAST_DELEGATE... •DECLARE_DYNAMIC_DELEGATE... •DECLARE_DYNAMIC_MULTICAST_DELEGATE... •DECLARE_DYNAMIC_DELEGATE... •DECLARE_DYNAMIC_MULTICAST_DELEGATE... 

建立好委托之后,就可以使用一系列的Bind函数把函数指针绑定进去(也可以直接绑定另一个委托),然后使用一系列Execute函数执行这个委托。(注意,多播委托绑定的时候调用的是Add系列,实行的时候调用的是Broadcast)
然后还要注意Bind一系列的后缀,BindRaw是类内成员函数,BindStatic是类外全局函数,BindSP还需要一个SharedRef对象,Bind本身是绑定另一个委托,别调用错了,参数都不一样。

注意,多播委托的Add接受的参数看不懂,不会给里边挂新函数,但是没关系,我们可以查看这个多播委托的类型的宏实现,分析出他的返回值和参数,但后就可以通过

__Internal_AddDynamic

这个内部函数来挂委托,他接受的参数是调用的对象(一般是this)函数指针,和函数名(一定要写全“类名::函数名”,如果不想写函数全名,可以使用AddDynamic宏,在delegate内不会智能提示,但是这个宏在全局是实现了的,他接受一个函数指针,但是不要求函数全名),其中它要求的函数指针类型是

FDelegate::template TMethodPtrResolver< UserClass >::FMethodPtr

完全可以看出这个是函数指针(MethodPtr),参数传一个函数指针进去,它内部会把那个指针和你的userobject一起打包成一个delegate,本质和传委托是一样的(就是使用delegate的create系列静态方法,把你的函数指针创建成一个委托)

而我们通过宏声明的委托类型实际上是

typedef TBaseDelegate<RetValue,Param1,Param2......> yourdelegatename;

是一个TBaseDelegate的泛型实例。

总结:如果参数是TBaseDelegate类型,就穿一个委托实例进去,如果是FMethodPtr类型,就传函数指针进去(比如你使用Timer的setTimer函数,就有要委托和要函数指针两个版本的setTimer函数,看清楚参数再用)

0 0