在使用UE5开发游戏中,关于类人的移动逻辑都封装在CharacterMovementComponent这个组件中的,常常使用ACharacter和CharacterMovementComponent搭配使用,从而快速实现人物移动。
本文主要解析源码是如何从玩家输入体现到角色移动的。
UE5中移动的本质
阅读源代码之前,我们需要非常明确一个要点,在不加任何修饰的情形下,移动的本质是玩家每一帧输入的上下左右的方向值加上角色当前位置得出的结果,再将这个结果重新设置为角色的新位置。在明白了移动的本质后,接下来我们才不会被那些复杂的向量计算、条件判断、网络预测、物理所影响,以直击代码中移动的根本。
源码解析
首先还是从最熟悉的蓝图作为入口,如下图AddMovementInput方法,需要的时传入一个方向和缩放值,这个方向是通过Controller的旋转转换而得,缩放值是玩家输入向量值,范围是-1,1。
进入AddMovementInput方法,第一个条件分支是在寻找其MovementComponent,针对于Character,一般获得是被覆盖之后的CharacterMovementComponent,即会进入第一个分支AddInputVector。
跟进AddInputVector,这个MovementComponent找到其Owner,也就是Pawn,将输入传进去。
Pawn在收到输入的加速度向量,将其叠加于存在的ControlInputVector以备后用,这里就需要关注ControlInputVector的使用情况。
其通过Internal_ConsumeMovementInputVector获取,同时PawnMovementComponent提供一个获取方法。
上述已经将玩家的输入存在了Pawn的ControlInputVector中待处理。
接下来看看CharacterMovementComponent.cpp是如何处理的?
在CharacterMovementComponent的Tick中,发现其调用了父类ConsumeInputVector方法来获取其输入向量。
继续往下,Tick调用了ControlledCharacterMove,将输入向量和帧时间传入。
进入ControlledCharacterMove,这个方法中重新计算了一下加速度,然后针对权威端和主控端进行了区分。
这里先不考虑网络情况,看看权威端PerformMovement这个方法是怎么执行移动的。
在PerformMovement中,去除大部分关于根运动的处理,实际改变位置是StartNewPhysics方法在处理。
深入进去后,StartNewPhysics方法是根据不同移动模式,进行不同的物理更新,这里我们就看看最常见的PhyWalking方法。
发现如下图,获取的Velocity,然后计算出当帧的Delta,如果不为0,则通过MoveAlongFloor处理移动速度,函数名大致可以看出这个方法是处理沿着地表进行移动。
进入MoveAlongFloor后,很清晰的看出通过传入的速度计算了水平的位移量,然后再沿着地面计算出加入Z的斜坡向量,通过SafeMoveUpdatedComponent应用位移量。
跟进SafeMoveUpdatedComponent方法后,一下就看到熟悉的MovedUpdatedComponent方法。
一路到最后,终于看到了SceneComponent的InternalSetWorldLocationAndRotation方法,将传入的位置信息,应用到了根组件上,从而更新人物的位置。
最后,对比常用的SetActorLocation方法,其实原理是完全一样的,只是CharacterComponent帮我们做了很多额外的事情,保证整个移动的正确性。
总结
在游戏开发中,基本离不开角色的移动,这也是游戏3C开发中非常重要的一部分,UE5帮我们实现了一套常用的移动逻辑,我们需要去了解其细节原理,以便更好的掌握并能够修改它来更快的达成自身游戏的需求。下一篇我们来看看网络下移动是如何处理的,尤其是移动的预测。