动画蓝图架构
Start, Stop, Idle, Cycle 四个状态
在基础状态机搭建起来后主要是这四个状态。
Start
同步组 Locomotion。两个事件,动画序列和序列时间动态。需要处理距离匹配
Idle
Cycle
同步组跟随start为Locomotion。动态设置sequence和play rate。距离匹配根据速度调整动画的播放速率
Stop
同不组的单独的Stop。动画和,输出时间都是动态,去掉循环播放。
- Update Stop Anim
首先是频道是否需要距离匹配
然后再调用接口,获得距离匹配的值,如果值不>0 那也不需要距离匹配。
如果需要距离匹配
如果不需要
Jump 状态
从起跳开始,通过导管分离起跳还是下落。
如果是起跳,需要有起跳动作和起跳循环,然后到底顶点状态。
如果是下落就直接进入顶点状态。
JumpStartLoop -> JumpApex 是指起跳什么时候到达顶点呢。这是一个物理问题。v = gt, 求 t。t < 0.4 就进入顶点状态然后播放顶点动画后进入下落循环。下落循环这里需要一个向下的射线检测,距离地面的距离 < 200 的时候到底FallLand状态
完成这一系列落地流程后,或者是其他跳跃状态中遇到了地面(JumpFallInterupSource)根据是否有加速度,过度到Cycle和Idle
同样的动画状态机有动画层实现。这里需要给动画蓝图接口添加五个层
- JumpStart
- JumpStartLoop
- JumpApex
- FallLoop
这四个都是直接连一个读表的动画就可以了,主要循环播放是否勾选
- FallLand 比较复杂一点
因为要过度到Cycle Idle 状态所以需要设置同步组,动态设置序列时间是为了距离匹配。
Setup状态只需要把序列时间归零就可以了
Update
需要距离匹配
步幅适配
Animation Warping
主要是这个节点。需要一个alpha 和一个速度
- Start状态
在Fullbody Start 连一个这个东西。注意这里的参数设置。
关于这个混合度,在Set Up Start Anim的时候制空一下,在Update的时候算一下。
float UCwlAnimLocomotion::UpdateStrideWarpingStartAlpha(float ExplicitTime)
{
StrideWarpingStartAlpha = UKismetMathLibrary::MapRangeClamped(
ExplicitTime - StrideWarpingBlendInStartOffset, 0.f, StrideWarpingBlendInDuration, 0.f, 1.f);
return StrideWarpingStartAlpha;
}
新增
- 同理对于Cycle状态
需要一个混合都和一个速度。混合度在Update的最后算一下,主要是根据角色是否撞墙来调整步幅
用这个modify给Start Cycle动画添加同不组
四向运动(朝向扭曲)
计算移动方向,然后动态设置四个方向的起步动画
这只是四个方向,其他的部分通过朝向扭曲来弄
相关设置
同样的节点给循环状态和停止状态也弄一个
不过这里角度是没有偏移的。
Start, Cycle, Stop 三个地方按照类似的操作处理。
如果你比如左前和右后这种混合不太流畅,可能是动画的同不组没弄好。
回转运动
PivotSource是Cycle和Start。过度到Pivot的条件是速度和加速度方向是否相反。且不是在撞墙
Pivot->Stop是是否没有看加速度,优先级2
Pivot->Cycle 一条优先级2是由动画Anim Notify State 触发的
另一优先级3
(PS: 到这里代码写在actor component的计划炸了,重构了一波,现在代码都在父类Anim Instance里面)
这里状态由子类实现,绑定两个函数
====
====
然后我们来到子类动画层
缓存一些变量
逻辑1
逻辑2:
True:
False:
几个变量
- LastPivotTime: 复制后如果有正值,每次更新减掉delta time。
- PivotInitDirection
- PivotStartAcceleration
- Stride Warping Pivot Alpha
- Time At Pivot Stop
更新函数中:
如果LastPivotTime > 0。需要重新根据方向获取新的pivot动画,如果和当前值不一致,就需要切换。并刷新PivotStartAcceleration的值
然后判断加速度和速度方向是否相反:
True:
相反则需要做让回转运动停下的距离匹配
False:
否则就需要计算出一个回转运动应该播放的动画序列帧
原地转身
更新数据代码在 UpdateRootYawOffset
在这里添加一个旋转骨骼。
这里加一个更新函数