写在前面
主要是介绍一下触发器和计时器的使用;
一、在Actor中使用触发器
1. 新建一个C++类
- 创建的C++类也是放在Source文件夹中的Public和Private文件夹中;
- 选择Actor作为继承的父类;
- 头文件包括一个触发器和两个静态网格,它们共同组成一个Actor,定义如下:
cpp
文件的构造函数实现如下:
- 一些注意的点如下:
- 触发器的类型是
UBoxComponent
,也是一种不可见的非网格组件,这里同时设为根组件; - 由于触发器是不可见的,所以这里的碰撞类型仅设为
QueryOnly
,也就是仅返回碰撞信息,不发生实际的碰撞; - 由于触发器仅针对人物Pawn,因此除Pawn外的都忽略碰撞,仅设置对Pawn的碰撞,又因为是不可见,所以当碰撞发生时用重叠而不是阻挡;
- 触发器的类型是
2. 为触发器动态绑定响应事件函数
- 因为是动态绑定,所以如果是在构造函数中就绑定可能会有一些Bug;
- 这里推荐是在
BeginPlay()
中动态绑定响应事件函数到触发器上,如下:
- 其中,
OnOverlapBegin()
和OnOverlapEnd()
是两个自定义函数,在头文件的定义如下:
- 这两个自定义的函数因为要进行动态绑定,所以一定要声明
UFUNCTION()
宏; - 两个自定义函数的参数列表并不是随便填的,而是要到
PrimitiveComponent.h
中找它们对应绑定的签名的类型,它们对应的声明如下:
- 从声明中可以看出,
FComponentBeginOverlapSignature
是六参数SixParams
类型,所以对应的OnOverlapBegin()
需要六个参数,也就是声明中的最后的六个参数,把它们复制到参数列表中即可,记得去掉类型和变量之间的逗号; - 同样的,
FComponentEndOverlapSignature
是四参数FourParams
类型,所以对应的OnOverlapEnd()
需要四个参数,也就是声明中的最后的四个参数,把它们复制到参数列表中即可;
二、构建触发器蓝图类
- 用
AFloorSwitch
C++类派生一个蓝图类;
- 打开蓝图类:
- 给FloorSwitch和Door组件设置静态网格体;
- 然后调整它们的相对位置,大致如下:
- 注意,调整位置的时候可以点击左上角的透视,选择不同的视图进行对齐,这样比在三维空间中对齐方便;
- 最后把这个蓝图类拖到地图中,如下:
三、实现触发器功能
1. 头文件
- 在头文件中新增:
- 门和开关的初始位置成员变量;
- 升降门、升降开关成员函数;
- 更新门和开关位置成员函数;
- 注意:升降门、升降开关的成员函数均是蓝图实现而非C++实现,宏说明符是
BlueprintImplementableEvent
;
2. cpp实现
- 在
BeginPlay()
中获取门和开关的初始位置,如下:
- 实现动态绑定的响应事件函数,如下:
- 实现更新门和开关的成员函数,如下:
3. 蓝图实现
- 升降门、升降开关的四个成员函数需要在蓝图类中实现;
3.1 时间轴的使用
- 时间轴可以实现在一段时间内有特定的输出值;
- 在蓝图中右键搜索添加时间轴… 即可添加时间轴气泡到组件中,如下:
- 双击打开时间轴,点击左上角添加浮点型轨迹,并添加关键帧如下:
- 一些注意的点如下:
- X轴为时间轴,Y轴为输出值轴(这里修改了Y轴的名称为DoorPosition);
- 在二维网格中右键即可添加关键帧到xxx;
- 点击关键帧的白色菱形点,可以通过输入来修改它的时间(X) 和值(Y);
- 长度的值表示输出值的总时间,但可以通过勾选使用最后一个关键帧? 将输出时间截断到最后一个关键帧上;
- 按住Ctrl键选中两个关键帧,在其中一个关键帧上右键进行关键帧插值平滑两帧之间的直线,也就是平滑输出的值,如下:
- 同理,开关的时间轴Switch Timeline的设置如下:
- 一些注意的点如下:
- 之所以是最后输出
-20
是因为此时开关的网格体正好可以降到地面以下,这也是我们想要得到的效果; - 开关网格体向下移动20后的左透视图如下:
- 之所以是最后输出
3.2 函数的蓝图实现
- 函数的蓝图实现如下:
四、实现定时器功能
1. 头文件
- 头文件增加计时器句柄、关门间隔的时间和控制关门的函数,如下:
2. cpp实现
- 在构造函数中初始化关门时间:
- 实现关门函数,如下:
- 修改动态绑定的响应事件函数,如下:
- 一些注意的点如下:
- 在
OnOverlapEnd()
中,也就是Pawn离开触发器后,不是马上就把门和开关复原,而是启动计时器,在间隔一段时间后在调用CloseDoor()
函数; CloseDoor()
函数中就是调用了将门和开关复原的函数;- 在
OnOverlapBegin
中,也就是Pawn踏上触发器后,需要将计时器停止而且重置,这样如果之前的计时器还没有计时完成(也就是还没有调用CloseDoor()
函数),则不会继续往下计时导致门还会被关上;
- 在
五、将Actor放置在地图中
1. 使用地图中的资源
- 地图中的网格体都是可以被再次使用的;
- 选中需要的网格体,在世界大纲视图中右键,点击浏览至资源,就可以打开该资源的所在位置;
- 在内容浏览器中选中该资源,然后到细节面板的静态网格体属性中,点击左箭头按键即可选择当前内容浏览器中选中的资源;
- 替换网格后的组件还需要重新调整大小、位置和旋转方向,如下:
2. 在地图中移动Actor
- 在地图中选中Actor,右键->控制xxx,可以很方便地移动Actor;
- 点击左上角的按钮可以退出Actor的控制视角;
- 修改Actor细节面板中的变换,把它放到合适的位置,如下:
-
一些注意的点如下:
- 可以在世界大纲视图中选择其中的Actor,效果和在地图中选中是一样的,而且可以快速搜索想要控制的Actor;
- 可以点击世界大纲视图的左侧眼睛,令地图中的Actor不可见(但在游戏开始时仍然是可见的);
-
最后把对应的墙删掉,即可完成一个自动门的Actor;