AdvancedLocomotionSystemV4分析(一):移动和脚步IK
最近对UE4商城
AdvancedLocomotionSysemV4
进行了一波初步分析,感觉这个项目已经包含了大多数情况能用得到的动画表现,从移动表现中比较容易出问题的脚步问题到IK、攀爬、翻滚、布娃娃以及动作叠加等模块都有讲到打算参考这个项目的思路重新实现一边动画逻辑,顺便对其中重要的模块和知识点记录一下
这一篇先从基础的移动逻辑,包括转身、起跳等,再顺带看一下脚步IK的实现
AdvancedLocomotionSystem分析(二):攀爬系统
AdvancedLocomotionSystemV4分析(三):动作叠加
AdvancedLocomotionSystemV4分析(四):布娃娃和起身
AdvancedLocomotionSystemV4分析(五):镜头
数据结构
首先先把移动和姿态相关的数据结构拎出来看一看,会用到很多枚举和结构体
Enum
MovementState/移动状态
- Grounded
- InAir
- Mantling(攀爬)
- Ragdoll
MovementAction/移动行为
- LowMantle
- HighMantle
- Rolling
- GetUp
RotationMode
- LockingDirection
- VelocityDirection
- Aimming
Gait/步态
- Walking
- Running
- Sprinting
ViewMode
- FirstPerson
- ThirdPerson
Struct
FDynamicMontage
用于动态播放蒙太奇,这个是鼠标拖动视角后的脚步的蒙太奇动画
FLean
倾斜参数
FMovementSetting
移动数据,配置各种移动速度和移动旋转相关的曲线参数
这边还包括了2层,分别对应3种旋转模式和2种视角的数据
然后到表格里配置3种形式的参数
FTurnInPlaceAssets
转身参数,也是用于播放蒙太奇,这个是移动视角到一定角度以后的转身动作
FVelocityBlend
4方向的权重值(混合值),非常不同于一般理解的用一个方向的概念,这里用了一4方向单独的浮点值来控制混合
角色逻辑
Tick
现关的tick
逻辑就以上几个
设置必要参数/SetEssentialValue
这个函数主要目的是计算并设置一些动画蓝图必要的参数,比如加速度、速度等
- 加速度
并非直接去移动组件拿实时加速度,而是自己计算2帧之间的速度差来计算加速度
- 速度
这个比较简单
- 移动输入值
一个用当前加速度来设置的移动输入浮点值和布尔值,在动画蓝图里也是蛮重要的
- 视口旋转速率
2帧之间的朝向插值来得到的旋转速率
步态设置/UpdateMovement
主要设置枚举Gait
,这里需要提一下,按键得到的步态并不一定是最终的步态
DesiredGait
期望步态来自于事件输入,可以自定义
上图对不同姿态不同视口等做了一定约束/筛选,比如在Aimming
姿势下不能出现Sprint
上图种,根据实际速度来决定真实的步态,跟期望步态可能会不同,因为有加速减速的存在,直到这个过程到达所需的速度才真的设置步态
然后根据不同的情况设置不同的真正的速度、加速度、摩擦力等参数
更新旋转/updateRotation
说到角色旋转,我们要看一下角色几个很关键的参数
- bUseControllerRotationYaw : false
- CharacterMovement.bOrientRotationToMovement:false
以上2个参数都是false,意味着我们角色的朝向全靠我们逻辑来控制了
先看一个简单的插值计算函数
基本上大多数的角色旋转都是用这个函数实现的,做了2步插值计算
然后对于地面的速度做了一个计算,读取了配置参数的曲线信息,我们任意打开一个曲线看一下
上图是不同状态下的旋转速率,0=5,3=20
移动数据是BeginPlay的时候读表获取的
然后根据不同视角、旋转模式等进行不同的插值计算
然后还有一种旋转方式稍微不容易理解一点,需要注意的是如果动画制作的时候不是用30帧的,下图中的30帧处需要替换为对应的帧数
从曲线等到值来动态设置旋转值
这个曲线挂在转身动画里面,比如右转90度的曲线
动画修改器:添加根骨骼运动曲线
根骨骼旋转信息的曲线我们用修改器来制作,思路就是对比2帧之间的旋转插值然后添加数据点
缓存数据/CacheValus
就是存一下2个旧的数据,上述逻辑中用到的对比2帧数据差的
数据接口
如图所示,把必要参数都通过接口得到
动画蓝图
逻辑视图
主要逻辑就是Tick和通知两部分
在Tick中主要是如下几个方法
UpdateCharacterInfo
从角色要到必要的参数
UpdateMovementValues
这里比较有用的是计算VelocityBlend
的思路
如上图,重点是把世界速度转换成本地的归一化速度
然后是计算本地加速度和倾斜角度,加速度直接决定了倾斜角度
然后是计算步长,跟速度挂钩,从曲线中获取信息,下图中表示了曲线对应的大概的速度范围
计算站立动画播放速率:跟曲线Weight_Gait
有关联,一般设置2为跑步,3为冲刺的速率
UpdateRotation
旋转相关的参数,下图所示比较简单
后面还有关于转身的方法和通知,留到下面单独讲
动画视图
先来看一下动画视图的跟移动和IK有关系的主视图,原版工程还有很多层级,现在先不拿进来
BaseLayer
LocomotionCycles
这里就直接进入对应的动画层
第一下有点难以理解,为什么要分6个,一般理解上要么4个要么8个
理性分析以后,我们需要考虑一个穿帮问题,拿我们一般用的单个混合空间,横竖轴分别对应移动方向和移动速度来说,经常在4个斜角中的2个斜角会出现脚步严重穿插问题,用过的应该都能理解,现在这个设计思路就是几乎完美的解决了这个问题
比如走路一共有6个动作
我们如果的移动顺序是 前->右->后
那么动画的播放顺序是 F->RF->RB->B
如果是前->左->后
动画顺序是F->LF->LB->B
我们再去看动画具体表现
LF和RB都是右脚在前左脚在后,如下图
RF和LR如下图
而前和后都是正面朝向的就不贴图了
所以这种混合方式就避免了左右脚前后问题的混合,当然也意味着动画师得多做几份动画了
上图是MoveRF的状态机,需要注意的是RF对立面混合的就是前面所说的,脚步前后一致的LB,当然一般情况下,VelocityBlend
的R值和L值也不会同时大于0
每个状态机的进入都有一个通知,直接设置了方向枚举,这个枚举变量用于停步的逻辑,后面细讲
在这个动画层还有一些逻辑,如下图所示比较容易理解
LocomotionDetail
主要叠加了走路到跑步或者冲刺的启动动画叠加,如上面的动图
2个类似的状态机区别主要就是直接从静态到跑步还是从完整的走路姿势切换到跑步,从叠加上区别就是StartPostion
的不同
LocomotionStates
这里主要实现了2部分内容
- 原地/移动/停步的切换
- 原地转身动画
- Stop
用动画曲线来判定脚的位置,如下图
上图是跑步的位置曲线,重定向过来的曲线信息会有些许区别,比如直线变曲线,但是大致相同
基本上是右脚踩下=1,左脚踩下=-1
对于脚没有完全踩下的节点会复杂一些,先看一个全图
看一下骨骼分层
那么下面的混合大概思路就是根据不同的移动方向和不同的方向枚举,这2个变量之前都讲过,这里分别处理
混合的动作都是各个方向的走路动画的某个时间点的单帧动画
- 转身
转身动作是特殊情况的拖动,循环播放的形式
动画速率跟镜头旋转速度有关系
看一下具体的判定条件
言下之意就是瞄准方式或者第一人称的模式都是这样旋转的
MainMovement
此状态机用来控制地面和空中的姿势切换
用MovementState
和Jumped
分别判断是主动起跳和是被动自由落体
逻辑上主动起跳是先修改布尔值再更新枚举值
- 起跳
几个必要的变量计算
思路是在下落过程中计算得到速度和地面预判值
预判值用射线检测得到,最后得到效果是落地的瞬间叠加了手臂上扬的动作
内部状态机如上图
根据起跳时脚的位置来决定起跳初始动画,即一般意义上的JumpStart的动作,此动作为过渡性动作,结束以后自动跳转到下一个状态机
下一个状态机是空中循环,虽然是循环播放,但是无条件跳转到Flai
动作(一个手舞足蹈的下落动作)
脚步IK
脚步IK和停步其实要放一起说,因为停步的时候也用到了IK的一部分功能用来把脚收回去
这里加了很多虚拟骨骼
- foot_target_r:用来判断跨步是否比较大
- ik_foot_r_Offset:控制
TwoBoneIK
的Effector
,即IK效果的主要控制节点 - ik_knee_target_r:膝盖位置,
TwoBoneIK
的Joint
节点,即IK效果的方向参考点
- IK动画视图
动画视图比较简单,难点是计算方式
找到Tick逻辑里的UpdateFootIK
方法
从里面一点点分析
SetFootLocking
这里不细究了,思路就是得到当前动画的FootLock
曲线信息,有权重就意味着需要锁定脚步位置,锁定的时候即抵消了TwoBone IK
的Effector
骨骼的影响
SetFootOffset
这里会一直打射线计算地面点,得到具体的脚步的位置,然后插值计算放置跳帧
脚步IK逻辑不是很多,但是我这里重新实现的时候发现了很多细节问题,效果很难到达预期,具体可以详细参考工程