Unreal Blueprint Interface蓝图接口详解

167 阅读6分钟

说点废话,之前主要是做Unity,因为公司业务的原因,虽然专门学了Unity热更、shader、帧同步、编辑器扩展、各种设计模式等,但是很多东西一直也没怎么用。后来公司准备部分业务用UE做,当然Unity这块也没丢弃。当时我纠结了很久,是要继续深耕Unity,还是再学学UE?

后来觉得,东西是怎么学都学不完的,所以最好的办法就是提高学习能力,有需要,能尽快学会并应用就很好,所以既然现在用得到UE,那就学学。

最近看到查理芒格的演讲,醍醐灌顶! 人应该不断地提升自己。我们应该多学习各学科的主要知识,而不是和细枝末节纠缠不清。我特别注重汲取各学科的主要知识,这样才不至于只见树木,不见森林。把各学科的主要知识融会贯通,能发挥出巨大的威力。

一、接口、普通类、抽象类

对比往往是快速理解一个概念最好的方法,本人之前先学的C#,后有学了Unity,用unity做了四年左右的建筑方面数字孪生的项目;所以在学Unreal的时候学C++的时候,我总会和Unity以及C#做对比,这样学起来效率会更高。

让我们先了解一下C++或者C#等编程语言中的接口的定义:

在C++中接口的定义是:接口描述了类的行为和功能,而不需要完成类的特定实现。

C++ 接口是使用抽象类来实现的,抽象类与数据抽象互不混淆,数据抽象是一个把实现细节与相关的数据分离开的概念。如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类。

class Box
{
   public:
      // 纯虚函数
      virtual double getVolume() = 0;
   private:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
};

设计抽象类(通常称为 ABC)的目的,是为了给其他类提供一个可以继承的适当的基类。抽象类不能被用于实例化对象,它只能作为接口使用。如果试图实例化一个抽象类的对象,会导致编译错误。

因此,如果一个 ABC 的子类需要被实例化,则必须实现每个虚函数,这也意味着 C++ 支持使用 ABC 声明接口。如果没有在派生类中重写纯虚函数,就尝试实例化该类的对象,会导致编译错误。

可用于实例化对象的类被称为具体类。 (以上是取自菜鸟教程)>www.runoob.com/cplusplus/c…

这里对比一下C#还是有些不同的,C++中你可以理解为接口就是抽象类,因为C++中并没有interface关键字,所以C++的接口是通过抽象类来实现的,所以C++中的接口应该理解为抽象类:

1.不能实例化;2.继承该接口的类必须实现该接口的所有虚函数;3.可以包含属性。

在Java和C#中有所不同,它们有interface关键字;所以抽象类和接口是有区别的:抽象类中可以定义属性、方法的实现,而接口中不能定义属性,方法也不能包含代码实现;共同点就是子类继承它们时,必须实现它们中的所有抽象方法或者接口中声明的方法,它们只能被继承来实现具体功能。

抽象类和接口与普通类相比,普通类的继承也可以由子类重写父类的方法,但是这种重写不是必须的,这好处就是更灵活,坏处就是有可能忘记重写,造成类的误用。

二、Unreal蓝图中的Blueprint Interface

如果你看明白编程语言中的接口的定义和用途,那么这就是蓝图中Blueprint Interface的定义和作用,因为蓝图中的就是通过编程语言来实现的。

1)先定义一个Blueprint Interface蓝图类

生成一个蓝图接口 蓝图接口可视化面板

从蓝图接口的可视化面板中可以看出,可以添加方法,这些就是代码中的虚方法;而且蓝图接口中这些虚方法是无法写具体的实现的,图中可以看出是灰色的,这和代码中的接口是一致的。

2)实现蓝图接口

先把接口添加到普通蓝图中,这个添加类似于继承,我测试过即使不在EventGraph中使用OnInteract编译也不会报错,所以我认为添加接口到蓝图中时,应该就重写了改虚方法,只不过是没有具体的实现内容,具体内容还是要在EventGraph中写,所以才能通过编译。 添加接口 实现接口功能

3)调用蓝图接口中的方法

上面是右键鼠标点击事件触发,当点击到物体时,执行该物体继承自接口并重写了的OnInteract方法。

猜想:这个蓝图接口的方法在所有蓝图中可以直接访问,其他自定义的事件也是可以的。EventGraph中编写逻辑时,例如调用某个事件或者某个方法,肯定是在调用之前先找到了这个类型实例的引用,上图中可以看出,Hit Actor返回的就是相应的引用,如果击中的物体没有该OnInteract方法,自然也就不会执行。

三、补充

蓝图接口与C++的接口还有一个不同点,在C++中接口都可以重写,无论是有无参数或者返回值;但是在蓝图接口中就不同了,蓝图接口中如果没有传入参数即Inputs,也没有返回值即Outputs,那么该接口可以是一个事件,当然也可以是一个函数,其内部无法添加功能;也无法直接拖入到EventGraph,只能右键搜索。如下图所示的OnInteract接口。 当接口有输入参数Inputs时,那么接口同上,该接口可以是一个事件,当然也可以是一个函数,其内部无法添加功能;也无法直接拖入到EventGraph,只能右键搜索;双击会进入相应的接口视图,如下图所示。 当接口有输出参数的时候,情况就和C++的接口比较类似了,可以直接拖入到EventGraph,也可以双击编辑添加新的功能,但是此时就无法作为事件使用了。如下图所示。

总结来说就是有输出参数时,蓝图接口就是一个函数,可以添加新的功能;如果没有输出参数,那么蓝图接口就是一个执行事件或者一个函数,但都无法编辑。