就是脑残死磕,你们如果有更好的方法一定要留言啊~~独乐乐不如众乐乐。
做推箱子的时候需要考虑脸是不是面对着箱子,不是必须90度,可以有一个-45~45度的范围。
摸索了一下,有几种做法和几个小白坑,这里列出来。
一、准备工作(实现跨蓝图修改变量)
-
准备一个名为
LightRobot
的玩家蓝图(pawn)
就用正常的配置操作即可,我这里写明LightRobot
是为了方便与截图中的名称一一对应。
-
准备一个名为
BP_Box
的角色蓝图(actor),其中放入Cube
立方体组件和Box
盒体碰撞组件。
Box
的四周比Cube
大一点,底顶比Cube
小一点。
注意: 需要将
Box
作为Cube
的子级,否则Cube移动后,Box
并不会跟随移动,下次想要推就没法激活了。
同理:DefaultSceneRoot
不会随着Cube
移动,因为它是根,是Cube
的父级,而父级不会跟随子级移动。
这点很重要哦,搞错的话将无法获取正确的位置。
-
准备一个动画蓝图
LightRobot_ABP
,其中放入一个变量isPush
来确定是否激活推动动画
动画部分不在本文展开。
-
使用重叠事件来更改
LightRobot_ABP
中isPush
的值
这个流程人物只要走到箱子附近就会释放推动动画,哪怕人物是背对着箱子的。
两个知识点和流程
知识点:
- 跨蓝图修改需要用
Castto...
节点,翻译为类型转换为~~
(明明是施法-_-!); - 要读取动画蓝图则需要先获取
动画实例
。
流程:
(1) 重叠事件发生,于是从一堆Other Actor
碰撞到的物体中Cast to BP_LightRobot
找到玩家蓝图;
(2) 再Get Mesh
找到该玩家蓝图下的网格体;
(3) 这个网格体下有动画,于是Get Anim Instance
获取动画实例;
(4) 在用Cast To LightRobot_ABP
从一堆动画中找到玩家用的动画蓝图;
(5) 最后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.根据角色坐标射出射线
在本例中用这个方法也没问题,反正就是胸口射出射线么,用这个还不需要查询根组件,效率更高一点。
也可以把其中向前的向量直接简写为如下
小知识:
乘法默认情况下两个乘数的单位是相同的,但是你可以选中其中一个数右键菜单更改其单位。
参考:
Using a Single Line Trace (Raycast) by Channel
虚幻引擎图文笔记:如何实现角色推箱子(使用Line Trace By Channel实现)
虚幻引擎图文笔记:如何实现角色推箱子(使用碰撞实现的初级版)