UE5-蓝图通信 :接口/事件分发器/引用

开篇先导:

#1 为什么要用反射?
#1.1 蓝图可编辑实例
#1.2 序列化和反序列化
#1.3 游戏状态保存和恢复
#2 4类常见通信方式
#3 蓝图接口 (BluePrint Interface)
#4 事件分发器(Event Dispatch)
#5 使用区别和注意事项
#1:为什么要用反射

当我们在使用 Unreal Engine 5(UE5)进行游戏开发时,经常需要在游戏运行时处理大量的对象{object)以及他自个的属性。这些对象和属性可能来自于游戏场景的一个“box奖励箱”、角色(血量,buff)、物品(效果)等各种元素。在处理这些对象和属性时,我们便需要使用到UE5为我们提供的反射机制。
蓝图接口,和事件分发器,这两个功能,他们都离不开UE的反射,没有反射,这一切的一切都无法实现。他们都是基于这个地基之上的高楼。
反射是指在运行时获取一个对象的类型和属性信息,然后使用这些信息来执行操作。也就是,运行时类型信息可用。
在 UE5 中,反射是通过使用 UClass、UObject 和 UProperty 等类来实现的。想了解最底层,可以去知乎看ue社区经理,大钊的专栏。
下面说下反射在 UE5 中的一些常见应用场景。
1.1 蓝图可编辑实例(Instance Editable)
蓝图可编辑(Instance Editable)实例,允许开发者(你)在运行时动态地创建和编辑类的实例。在创建实例时,UE5反射系统会使用元数据来初始化实例的属性。开发者可以使用 细节(Details) 面板来编辑类的属性,并使用 事件面板图表(就是蓝图编辑器界面)来定义类的行为。这样,开发者就可以通过蓝图来创建和编辑对象,而不需要编写 C++ 代码。
1.2 序列化和反序列化
序列化是指将对象转换为一系列二进制数据(因为cpu只认二进制)的过程,而反序列化是指将这些二进制数据转换回对象的过程。在序列化和反序列化过程中,反射可以帮助我们动态地获取对象的属性信息,并将其转换为二进制数据或者将二进制数据转换回对象。
1.3 游戏状态保存和恢复
在游戏运行的时候,有时候我们需要保存和恢复游戏的状态(存档读档)。这个时候反射也可以派上用场。我们可以使用反射来获取游戏对象的属性值,并将其保存为一系列数据。当需要恢复游戏状态时,我们可以使用这些数据来重新创建游戏对象,并将其属性值设置为之前保存的值。
1.4 具体来说
蓝图可编辑实例使用了 UE5 的这套反射系统,通过对对象属性进行元数据标注,在运行时动态地创建类的实例。反射系统会读取类的元数据,包括属性名称、类型、默认值等信息,然后将其用于创建实例。
在创建实例时,反射系统会使用元数据来初始化实例的属性。

#2 4类常见通信方式
2.1 直接通信 对象引用


2.2 类型转换

2.3 蓝图接口(Blueprint Interface)

2.4 事件分发器(EventDispatcher)

还有一个是关卡蓝图,获取对象引用来控制actor,一般不常用。

#3 蓝图接口 (BluePrint Interface)

在UE5中蓝图接口和事件分发器。
是咱们常用的两种蓝图通信机制,它们都可以用于不同蓝图之间的通信(比如开关button对象和灯泡(light)对象,进行通信)。
本文我们将介绍蓝图接口和事件分发器的使用区别、注意事项和使用场景。

1 使用方法:
蓝图接口可以在一个蓝图中定义一个接口方法,并在其他蓝图中实现该接口方法。使用蓝图接口,需要注意以下几点:
① 接口方法必须在接口中定义,并且必须有输入和输出参数。

② 接口必须在蓝图中被实现,否则在调用该接口时会抛出错误。

③ 一个蓝图可以实现多个接口,也可以实现同一个接口的多个版本。
④ 蓝图接口只能在蓝图之间传递数据和消息,不能直接调用函数或方法。

使用场景
蓝图接口通常用于以下场景:
① 当多个蓝图需要共享相同的逻辑或数据时,可以通过定义一个蓝图接口,在多个蓝图中实现该接口,从而实现数据或消息的共享。
② 当需要修改或扩展一个蓝图的功能时,可以通过定义一个新的接口,并在原有蓝图中实现该接口,从而实现功能的扩展。
注意事项:
蓝图接口只能在蓝图内部使用,不能被C++代码调用。
如果一个蓝图实现了一个蓝图接口,但没有实现接口中定义的所有函数,那么在编译时会产生警告。
如果多个蓝图实现了同一个蓝图接口,那么在使用接口时需要注意具体调用哪个实现。
#4 事件分发器(Event Dispatch)
在这种方法中,负责发送事件的Actor需要创建一个 事件分发器(Event Dispatcher)

所有监听该事件的Actor都会订阅该事件分发器。

此通信方法采用一对多关系,每当当前Actor触发事件分发器后,监听该Actor的其他Actor都会收到通知。
4.1使用方法
事件分发器(Event Dispatch)是一种通用的消息传递机制,它可以在一个蓝图中定义一个事件,并在其他蓝图中调用该事件。使用事件分发器,需要注意以下几点:
① 事件必须在蓝图中定义。
② 事件分发器可以在任何蓝图中调用,可以是同一蓝图中的其他事件,也可以是不同蓝图之间的事件。
③ 事件分发器可以通过调用多个不同的事件实现对同一消息的广播。
④ 事件分发器可以在蓝图之间传递消息和数据,也可以调用其他蓝图中的函数或方法。
4.2使用场景
事件分发器通常用于以下场景:
当需要在多个蓝图中实现相同的功能时,可以通过定义一个事件,在多个蓝图中调用该事件,从而实现数据或消息的共享。
当需要广播消息时,可以通过调用事件分发器实现消息的广播。
当需要调用其他蓝图中的函数或方法时,可以通过调用事件分发器实现对其他蓝图的调用。
注意事项:
事件分发器是一种异步机制,事件发送方和接收方之间不存在直接的调用关系,因此需要注意事件的发送和接收时序。
事件分发器是一种松散耦合的机制,可以在不同的蓝图之间进行数据传
五、使用区别和注意事项
蓝图接口和事件分发器都可以实现蓝图之间的通信,但它们的使用方法和适用场景不同。
在使用时需要注意以下几点:
1. 使用场景的区别
蓝图接口通常用于需要共享逻辑或数据的场景,例如不同角色的蓝图需要使用相同的功能或变量。而事件分发器通常用于消息广播的场景,例如游戏中需要触发某个事件时,可以通过事件分发器向所有需要接收该消息的蓝图发送消息。
2. 调用方式的不同
调用蓝图接口时,需要使用“实现接口”节点并将接口与实现进行绑定,然后才能调用接口方法。而调用事件分发器时,只需要在需要接收消息的蓝图中添加事件的响应节点,并将事件分发器与该节点进行绑定。
3. 数据传递的方式不同
蓝图接口和事件分发器都可以用于数据传递,但它们的传递方式不同。在使用蓝图接口时,数据是通过输入输出参数进行传递的,而在使用事件分发器时,数据是通过事件调用时所携带的参数进行传递的。
4. 适用范围的不同
蓝图接口和事件分发器都可以在同一蓝图中使用,但蓝图接口还可以在不同蓝图之间使用。而事件分发器只能在同一蓝图或基于同一蓝图的子蓝图之间使用。
5. 实现方式的不同
蓝图接口需要在蓝图中定义接口方法,并在实现接口的蓝图中添加相应的实现方法。而事件分发器只需要在蓝图中定义事件,并在需要接收该事件的蓝图中添加相应的响应节点即可。
在UE5中,在关卡蓝图里调用某个对象的事件和在一个单独的蓝图类里调用某个对象的事件有一些区别:
作用域不同:关卡蓝图里的事件只在该关卡中生效,而单独的蓝图类可以在多个关卡中重复使用。
对象绑定方式不同:在关卡蓝图里,对象通常是通过在场景中直接放置或者在关卡蓝图中创建的,而在单独的蓝图类里,通常需要手动将对象引用传递给该类。
调用方式不同:在关卡蓝图里,通常通过拖拽事件节点来调用某个对象的事件,而在单独的蓝图类里,可以通过直接调用对象的事件函数来实现。
维护和管理不同:单独的蓝图类可以更方便地进行维护和管理,因为它们是一个独立的模块,可以进行单独的测试和修改,而关卡蓝图通常是和场景紧密耦合的,修改和测试会相对麻烦一些。
总的来说,在使用时需要根据具体情况选择使用哪种方式,但单独的蓝图类通常更加方便和灵活。