UE4 C++ 浅析委托并实现一个简单的例子
什么是委托?
我们先来看看官方的解释:
委托 是一种泛型但类型安全的方式,可在C++对象上调用成员函数。可使用委托动态绑定到任意对象的成员函数,之后在该对象上调用函数,即使调用程序不知对象类型也可进行操作。复制委托对象很安全。你也可以利用值传递委托,但这样操作需要在堆上分配内存,因此通常并不推荐。请尽量通过引用传递委托。虚幻引擎共支持三种类型的委托:单播委托,多播委托,和动态委托。
光是看定义可能不是很好理解,我们知道在计网中,单播和多播的意思是主机之间的一对一或者多对多通讯,在UE4中我们没有主机,所以并不是计网中的意思
单播委托的意思就是可以使用一个Actor事件绑定到另外一个Actor某个函数,即可以调用不知道该对象类型的函数。
(图取自B站up唯乐来了)
对于实现一个开关门/灯的过程来说,就是我们可以设置一个Trigger,通过绑定Trigger与门,来实现当碰撞触发或者重叠触发等事件只要触发Trigger以后就可以调用到门的函数,从而来实现开关门。
就这这个例子,我们来看看委托是如何实现的:
加入当一个委托被建立完毕之后,它不会通过Trigger直接把委托信息传送给门,而是先会把委托信息传递给一个管理委托系统,通过管理委托系统再将信息传递给绑定委托的物体。这里使用管理委托的原因很简单,当一个游戏中所需要委托太多,如果不使用一个系统对其进行管理,那将会变得非常的混乱。
首先我们要知道管理委托的系统在UE4中叫做声明委托
为了声明委托,我们要设置一个默认的GameMode,将声明委托放在里面。
我们要做的是,新建一个GameMode(一般新建项目都会有,直接用),然后记得,打开你的地图,WorldSettting里面把GameMode改成自己的GameMode(默认是无)这里非常重要!
然后如黄色框所示,我们需要声明一个委托,第一个参数是委托名,委托名是自己可定义的,至于如果你所需要声明的委托需要传参数,就在后面添加_XXXParam(XXX指需要传参数的个数),如果要声明多播就在中间加上_MULTICAST。
这样我们就知道,我们黄色部分声明的是一个 多播的,有一个bool参数的,委托名为FMyTrigger(为了符合UE中命名规则,前面加上F)的委托。
声明完之后,我们在红色部分对于进行实例化(使用Public关键字,因为我们希望其他类对他进行调用)
声明完委托以后,我们就要对委托进行绑定了。
我们首先新建一个名为MyDoor的Actor,然后在其中加入StaticMeshComponent,然后我们定义一个DoorState函数,当Trigger事件触发之后,我们调用DoorState函数,用来对门进行开关。
MyDoor.Cpp实现:
这里重点讲解下红色框部分,
我们要绑定某个函数首先就要先找到我们的委托名,我们的委托名定义在自定义的GameMode里面
所以我们使用GetWorld()再使用GetGamoMode得到GameMode的父类AGameModeBase,再通过Cast<>操作得到继承自AGameModeBase的我们的子类AUE_ProjectGameModeBase.
要实现绑定,我们只需要再MyTrigger执行特定的方法:这里是多播绑定,所以使用的是AddUObject(,)后面的参数是传递函数的引用
当然,对于单播委托,还有更多的绑定方法:
这里的OpenDoor和CloseDoor函数,我们想通过蓝图实现从而达到渐渐开门的效果,蓝图实现如下:
至此,我们的委托绑定就已经完成了。
我们再来看看如何执行委托
在上面一个蓝色框,我们定义了一个BoxComponent用来得到碰撞事件,从而触发委托,在红色框是我们的执行委托函数,这里我们要传递一个参数value(这也是为什么我们开始声明时需要声明一个参数的原因)
执行委托部分,我们也要调用自己的委托关键字,所以前面与绑定委托一致,就不再赘述,唯一不同的地方就是红色框,这里我们时多播,所以执行的时Broadcast,这会把信息广播给所有已经绑定的对象,如果是单播时有如下:
当然,我们最后仅仅只是把执行广播写在了碰撞事件里面,我们要完成执行还需要重写碰撞事件(上上图蓝色框):
这里我们将BeginOverlap和EndOverlap分别绑定到我们写的函数上。
你会发现在我这里会有很多的参数,虽然都用不到。但是这里的参数的必须的(还没搞清楚为什么)
要怎么得到这个参数呢?我们已BeginOverlap为例,我们使用IDE自带的查看详细代码的功能(ctrl+ 鼠标左键),
我们打开OnComponentBeginOverlap(如下图红色框所示)
打开之后我们发现它其实也是一个东西的实例,我们再对这个进行打开
得到这个后缀为SixParams的东西的声明,我们取它的后12位参数(参数的名字与类型是分开的,实际上我们需要6个实际的参数)再放到自己定义的函数里面,作为默认参数就可以了。
注:这里不是每一个事件都一样,如EndOverlap,我们打开之后如下,选择只有四个参数的
至此委托就已经介绍完毕,如果还是看不懂这个过程,可以查看本文第二个参考链接的一位Up主的视频。
参考链接:
Delegates and Lamba Functions in Unreal Engine | 虚幻引擎5.0文档
【ue4_C++】用委托(代理)实现开门、开灯效果_虚幻引擎_C++_蓝图_哔哩哔哩_bilibili