UE5制作推箱子游戏机制:获取物体与角色朝向角度及跨蓝图变量修改
UE5制作推箱子游戏机制:获取物体与角色朝向角度及跨蓝图变量修改
在虚幻引擎5(UE5)中制作推箱子游戏机制时,如何判断玩家是否正对箱子并进行推动物体的操作是一个常见的技术问题。本文将详细介绍如何通过获取物体与角色朝向的角度,以及如何实现跨蓝图修改变量,帮助开发者实现这一功能。
准备工作:实现跨蓝图修改变量
1. 创建玩家蓝图
创建一个名为 LightRobot
的玩家蓝图(Pawn)。使用正常的配置操作即可。
2. 创建箱子蓝图
创建一个名为 BP_Box
的角色蓝图(Actor),其中包含 Cube
立方体组件和 Box
盒体碰撞组件。Box
的四周比 Cube
大一点,底顶比 Cube
小一点。
注意:需要将 Box
作为 Cube
的子级,否则 Cube
移动后,Box
并不会跟随移动,下次想要推就没法激活了。
同理:DefaultSceneRoot
不会随着 Cube
移动,因为它是根,是 Cube
的父级,而父级不会跟随子级移动。这点很重要哦,搞错的话将无法获取正确的位置。
3. 创建动画蓝图
创建一个动画蓝图 LightRobot_ABP
,其中包含一个变量 isPush
来确定是否激活推动动画。动画部分不在本文展开。
4. 使用重叠事件
使用重叠事件来更改 LightRobot_ABP
中 isPush
的值。这个流程人物只要走到箱子附近就会释放推动动画,哪怕人物是背对着箱子的。
两个知识点和流程
知识点:
跨蓝图修改需要用
Castto...
节点,翻译为类型转换为~~
;要读取动画蓝图则需要先获取
动画实例
。流程:
- 重叠事件发生,于是从一堆
Other Actor
碰撞到的物体中Cast to BP_LightRobot
找到玩家蓝图; - 再
Get Mesh
找到该玩家蓝图下的网格体; - 这个网格体下有动画,于是
Get Anim Instance
获取动画实例; - 在用
Cast To LightRobot_ABP
从一堆动画中找到玩家用的动画蓝图; - 最后
Set isPush
设置变量。
- 重叠事件发生,于是从一堆
下面的图片是从玩家蓝图中找到动画蓝图的顺序,看完是不是就清楚上面的流程了?
这些准备好后,现在开始正式判断角度。
根据位置判断
基本原理:
- 获得箱子的位置和玩家的位置,计算得到一个人到箱子的向量A;
- 获得玩家脸朝向的向量,其实就是前进的向量B;
- 计算得出A和B之间的夹角
不过这种方法并不精准哦,毕竟站在箱子边缘和站在箱子中间,本身就会产生角度,当然如果箱子不那么大,也够用了。
1. 通过Cube的相对位置来实现
我之前说过,在 BP_Box
蓝图中,Cube
是能动的,可根 self
是不会移动的,需要通过 Get Relactive Location
来获得 Cube
相对 DefaultSceneRoot
的位置。
这里的点积 Dot Product
和反余弦 Acos(Dgrees)
只要知道是比较两个向量后再换算成角度
2. 将Cube设置为根级来实现
这里直接调用 Cube
的位置,但是必须要将 Cube
作为根替换掉原来的 DefaultSceneRoot
,道理是一样的,因为根 DefaultSceneRoot
不会跟随子级 Cube
移动,那么当第一次重叠时能获得正确的角度,而第二次重叠时虽然箱子已经移动过位置了,但箱子的根位置还在原来的地方,于是就出错了。
根据射线判断
上面的方法是根据角色到物体的方向和角色前进方向来算出两个方向的夹角是否满足面对物体的要求。这个方法在遇到小物体是没问题,但遇到一个很大的物体时,就会出错了——当你站在物体边缘,这时候两个方向的角度已经很大了,就更不用提脸的朝向了。
然后就找到了真正的解决办法~~,应该也是真正常用的办法:“胸口射线法”,学会了这个方法基本可以解决90%以上的碰撞问题了;
简单来说就是:
- 当组件重叠事件激活时,从玩家胸口射出一根有指定方向和距离的射线;
- 当这个射线击中某个可以碰撞的物体时检测是否符合要求,符合则为真;
- 本例中因为触发盒体碰撞的范围离箱子很近,那么射线的第一个遇到的目标肯定是盒体,所以就为真了;
- 本例中的射线长度为1500,目的是为了测试时能看清射线,实际运行时是有问题的,因为你斜着箱子站的时候,射线虽然没有击中箱子,但可能击中更远的墙了,那么也会判定命中为真,所以射线长度设个50、100短一点的就行了。
- 注意
Ignore Self
需要去掉勾,因为打勾意味着忽略触发射线的Actor,也就是说射线投射将不会与触发该投射的Actor产生碰撞。由于我们是重叠时才会激活这个射线,重叠的前提就是玩家与箱子共同参与这个触发,如果此刻Ignore Self
为真的话,那么射线就会忽略掉箱子,直接穿到后面去了。
网上很多案例的情况与本文不同,他们并不涉及重叠事件,因此 Ignore Self
为真是没问题的,这点需要注意。
主要是理解 LineTraceByChannel
按通道进行线条追踪的用法:
- 其
start
开始值为玩家的当前位置(向量); - 其
End
结束值为玩家面对的方向多n个距离的位置(向量);
1. 根据世界坐标射出射线
2. 根据角色坐标射出射线
在本例中用这个方法也没问题,反正就是胸口射出射线么,用这个还不需要查询根组件,效率更高一点。
也可以把其中向前的向量直接简写为如下
小知识:
乘法默认情况下两个乘数的单位是相同的,但是你可以选中其中一个数右键菜单更改其单位。
参考: