复杂地形的攀爬翻越系统

很多 FPS 游戏比如和平精英,角色在运动中都可以攀爬或者翻越障碍物,这个系统很大程度上丰富了玩家的操作趣味性以及竞技性。

如何实现呢?
我在实现这个系统的过程中受到了 UE CharacterMovement 的启发,
首先检测前方障碍物和头顶障碍物,然后检测窗户以及落脚点,最后就是计算路径点,更新动画和路径。基本上就这些,具体实现如下,

检测前方和头顶的障碍物

  1. 检测前方障碍物,根据玩家可操作的距离以及 capsule 的半径,检测是否被阻挡;
  2. 检测上方障碍物,发射一个最大距离的射线,根据碰撞的距离决定后续阶段是否执行或者是否只执行翻越操作,因为攀爬需要的头顶距离更大一些;
    这里需要注意的是,我们使用了 Ray 和 Box 组合取代 Capsule,来增加性能,但是 Capsule 的底部是有弧度的,如果用 Box 的话,Box 底部会触碰到 Capsule 触碰不到的坡面,这不是我们想要的,
    我的解决办法也很简单,就是设置了一个 ForwardHitCheck 的 Error 值,利用这个值拉高Box的其实检测高度,你也猜到了这个值,ForwardHitCheckError,大概是等于 Capsule 的半径。
    以上检测通过之后,Vault 和 Climb 分别执行后续检测。

检测动作阶段

Vault,翻越
首先,检测前方障碍物是否有窗户,检测前方最大距离等于可以翻越的障碍物厚度,这里的 Box 的高度比下面翻越用到的 Box 的高度应该是小一些,这个根据策划需求和动画表现而定。
检测采取的是步进的方式,启动的坐标等最小可翻越厚度,根据固定距离步进检测,直到最大距离后停止。
这一步成功之后,也就是监测到有“窗户”,那么执行落地点检测,检测下方是否有障碍物,检测一定的距离,比如>=50,(掉落阶段),这个距离一定是大于某个值,不能太小,太小就不是翻越了,如果 Hit false,检测通过。
如果以上检测都没通过,那么执行攀爬检测。

Climb,攀爬
首先,同样的检测前方障碍物是否有窗户,这个检测的距离和半径是配置的,检测前方距离应该是角色可以落脚的最短距离,半径的话应该是角色站立的高度(HalfHeight),如果 Hit false,检测通过。
然后检测下方是否有障碍物,检测一定的距离,应该小于等于某个值比如<=50,(也就是坡度)如果 Hit true,检测通过。
如果攀爬和翻越有一个执行成功,那么继续执行下面的步骤。

攀爬和翻越都要检测落点的角度,大于一定的角度,比如70度,坡面太陡,角色是无法落脚的。

bool bWalkable = false;
WalkableFloorAngle = 70;
WalkableFloorZ = FMath::Cos(FMath::DegreesToRadians(WalkableFloorAngle));
bWalkable = Hit.ImpactNormal.Z >= WalkableFloorZ

计算动画路径

Vault 和 climb 检测的过程中,需要记录几个关键坐标点,障碍物的第一个拐点、第二个拐点(如果是翻越的话)、落点。
检测成功以后,根据以上的几个点,提取动画 RootMotion 的路径数据,提取动画的间隔建议在0.1s-0.033s之间,提取之后把对象空间的坐标转换到全局坐标系里,同时和动画同事约定几个 NotifyEvt,对应我们记录的几个坐标点,因为角色攀爬和翻越的高度和厚度都是可配置的,那么我们需要在这几个关键帧,更新我们计算出来的坐标点。
简单的更新是不行的,因为会造成强拉,视觉效果很不好,我们采用根据帧来计算插值的方式,比如我当前是第三帧,第一个拐点是第十帧,那么第三帧的 Z 轴(高度)的值应该是:

Alpha = 3/10;
TurnOffset = CalcFirstCrossPtZ - AnimFirstCrossPtPointZ;
AnimPointOffsetZ += FMath::Lerp(0.f, TurnOffset, Alpha);

然后更新 NotifyEvt 对应的点即可,
落点 Notify 开始之后,强行设置 Z 的值,保证动画落在地面上。
同样的道理,更新 XY 轴方向上的偏移,多了一步夹角的计算而已。

播放动画

播放动画,注意关闭 RootMotion。
Tick 更新提取的路径坐标,我们的动画是 30FPS 的帧率制作的,所以在游戏中,高帧率的情况下,要在两点之间插值保证顺滑。
有个细节,如果玩家翻越之后有很大的高度差,比如是跳崖,这个时候如果继续播放翻越的动作和路径点的话就有点假了,我的做法是,在翻越墙头的一刹那,检测下方的高度,如果是悬崖(大于一定高度),那么执行掉落逻辑。

性能优化

以上检测使用 ray 和 box 组合取代 capsule 来检测,用于提升性能。
同时注意监测的步进距离,不能太小,性能不好,也不能太多,不准确,当然最大翻越高度和厚度也会影响性能。

感谢阅读。