【ue4】【蓝图】通信篇

前言

上回书说到,我们可以使用蓝图的流程控制结构来实现一些比较复杂的逻辑,甚至是算法过程

但是这只是作为学习熟悉的一个环节,而非用药于实际开发中

当我们理清一个蓝图内部的一些控制之后,我们难免会想再进一步研究一下怎么搓和两个蓝图的人生大事,

再长远一点地看,我们以后难免还要操心解蓝图和CPP之间的关系

这就像人到了中年,操办完了儿子的婚事,还要再操心着女儿的婚事一样

我们这里就顺着这个思路去学习蓝图

本篇主要整理一下蓝图之间的通信方法,关于CPP的部分以后再说。

蓝图通信官链

直接蓝图通信

概念

当我们想要在一个蓝图里访问另一个蓝图中包含的 函数 事件 变量 等时

我们可以直接引用一个目标蓝图

即在 当前蓝图 里创建一个 目标蓝图 类型的变量

然后暴露这个变量

这样就可以在外面给这个变量赋值,使其直接引用一个 目标蓝图 变量

我们来看一个例子

我分别新建两个蓝图 bp_01bp_02

并且分别添加一个 Geometry 作为它们的 RootComponent

我们把它们放在世界里,并使其紧贴地面

现在我想实现的效果是,当我们控制角色经过 bp_01 的时候

bp_01 触发 其 overlap 事件,使它所引用的 bp_02 实例向上移动100个单位

那么我们就需要 bp_01 可以访问的到 bp_02, 这就是我们的目的了

首先我们打开 bp_01 蓝图,新建一个变量,并将变量类型其指定为 bp_02Object 类型

我们将这个变量暴露给外界,并设置它的 工具提示

直接点变量右边的 小眼睛 也可以

这个时候,我们就可以认为 bp_01 已经有了引用 bp_02 的能力,换句话说

bp_01 可以引用任何一个类型为 bp_02 的蓝图类

那么我们可以写触发事件了,注意在这之前要将 bp_01Collision 设置为 overlapOnlyPawn, 意思是只有 Pawn 类型可以通过它

触发事件如下

我们点击世界里的 bp_01实例,在其 细节 栏里选择 bp_02实例

测试一下,当我们的 Character 走到 bp_01 上时,bp_02 向上移动了100个单位

注意

如果要在 关卡蓝图 上引用一个蓝图,只需要在世界中选中这个蓝图实例,然后在关卡蓝图的事件表中右键,即可看到创建引用的选项

再次注意

由于在CPP中,父类引用可以指向子类,所以我们这里也可以将 bp_01 中的变量设置为 bp_02 的父类类型,如 ACtor

这个时候如果我们想使用子类特有的方法的话,就需要向下转型

还要注意一下

当我们新建一个函数时,可以将另一个蓝图类型作为函数的输入参数

这样在函数里就可以使用另一个蓝图类

类比于CPP的函数

使用场景

按开关(bp_01) 就可以打开门或灯(bp_02)

及其他 -- 两个 actor 需要相互通信

事件调度/分配器

概念

事件分配器被调用时,与它绑定的全部事件都会被调用

主要用于从单一源同时执行多个事件

我们来看一个例子

我们把前面的方法改成使用事件分配器试一下

首先,我们创建一个事件分配器

然后我们把它拖到事件图表中去,可以看到有好几个选项

我们选择 分配, 会出现一个 分配节点 和一个 自定义事件 节点

可以任意多次使用此节点

一旦绑定成功,每当我们调用此事件分配器时,就会调用所以与其绑定的事件

我们在 overlap 触发的时候调用此事件分配器,就实现了和上面一样的效果

CPP话外音 --

在CPP里,这个相当于 AddDynamic 函数的调用,我试了一下,同一个事件分配器确实可以多次调用 AddDynamic

1
2
welcome_ui->start_bt->OnClicked.AddDynamic(this, &ADGameGameModeBase::on_welcome_start_clicked);
welcome_ui->start_bt->OnClicked.AddDynamic(this, &ADGameGameModeBase::on_threeD_clicked);

使用场景

来自官网的经验,(来自实际的经验暂时还没有,这辈子都不会有的, 爱咋咋的^_^)

  • 需要从角色蓝图到关卡蓝图进行通信

    • 玩家升级后,开放之前的锁定区域

    • 玩家按下某个按键后,对关卡执行某种操作

  • 生成的 Actor 执行某种操作时触发事件

    • 生成一个 BossBoss 被消灭时触发一系列的事件 -- 掉装备 加经验,地图状态刷新 等等

    • 在关卡中生成一个道具(武器,回复剂等),并在道具被拾起时告知道具和角色

蓝图接口

概念

可类比于面向对象里的接口、

可以对 共有某些特征 但又 各不相同 的对象使用一种通用的方法交互

而这些对象又可重新定义接口的实现,以表达出不同的实现

我们来看一个例子

我们现在要实现一个简单的东西体验一下接口的用法

我们现在有两个 Actor

还有一个 Actor 用来触发事件,当我们的角色移动到这个 Actor 上面的时候,就会触发另外两个物体的移动事件

但是它是直接用 Get All Actors With Interface 来获取所有实现了某个接口的物体,但并不知道物体本身是什么

它的事件图表看起来是这样的

而前面那两个物体则实现了同一个接口,但是他们都重写了此接口的函数

所以当我们移动到第三个物体的时候,另外两个物体会朝不同的方向移动

我们首先来建立一个接口,并添加一个接口函数 running

然后在那两个物体的 类设置 里,都添加这个接口

这两个类的事件图表看起来像这样

然后运行一下,我们会发现,当我们的角色 overlap 到第三个物体上时,另外两个物体分别朝前面和右面移动

这就是接口最简单的例子了

使用场景

  • 数个蓝图中存在一些相似功能,但在调用后执行不同的效果
    • 玩家拥有一个喷射器,使用时会触发 Damage 事件, 树木和雪人蓝图都实现这个接口,但表现不同的效果
    • 玩家拥有一个 use 按钮,按下可执行 开门 ,关灯, 拾起道具等操作
    • 敌人拥有特殊能力,可基于玩家的体力值完成变化,执行不同的操作

蓝图投射

概念

Cast to 类型转换节点 -- 询问对象 是否为该对象的特殊版本

使用场景

  • 需要访问另一个蓝图的特殊版本。
    • 角色走进火焰中,导致体力值耗尽。
      • 投射到特殊的角色蓝图,以便访问并变更体力值。
    • 角色死亡,需要重新生成。
      • 投射到特殊的游戏模式蓝图,执行重新生成脚本。
  • 需要访问相同类的多个蓝图,并以相同方法进行修改。
    • 场景中拥有数盏灯,事件发生时需将它们开启或关闭。
      • 投射到灯蓝图并执行函数将灯关闭。
  • 需要访问一个特殊的子蓝图。
    • 存在基于一个动物蓝图(猫、狗、鸟)的数个蓝图,需要访问其中一个动物。
      • 投射到猫、狗和鸟,访问其相应的蓝图和特有功能。

总结

今天写的这些,都是很基础的概念上的东西

但是实践出真知,要想真正了解蓝图通信,为进一步深入学习 ue4 作打算

还需要不断地在实践中尝试才好

共勉 \(o)/