参考视频教程 从零开始的Lyra动画蓝图制作+解析

前期准备

  1. UE商城订阅LyraStarterGame,并创建项目,需要UE5.0及以上
  2. 打开项目,过滤动画序列,右键批量导出到一个文件夹
  3. 新建一个第三人称项目(c++或蓝图),如果是c++项目先生成GameMode的蓝图类
  4. 蓝图中左上角编译处设置, 在成功时自动保存勾选跳转到错误结点
  5. 将2导出的动画序列文件夹,拖到项目中,并选择骨骼模型
  6. 添加插件Animation Locomotion LibraryAnimation Warping(动画扭曲)
  7. Lyra中找到TurnYawAnimModifier,右键在文件夹视图中显示->回退到Animations目录->右键AnimModifiers->迁移到当前项目的Content

基础移动

  1. 复制BP_CharacterBP_GameMode,将BP_GameMode->Pawn设置成BP_Character,世界模式设置为BP_GameModeProject Setting->地图和模式->默认游戏模式->MyLyraGameMode
  2. BP_Character设置Auto Posses Player->Player 0Player Starter设置自动接受输入->玩家0

此时,可以正常操作人物了,但是还没有动画

  1. 创建动画蓝图ABP_LyraCharacter,添加基本动画状态

image

image

  1. 获取动画转换数据

Lyra使用Blueprint Thread Safe Update Animation来代替Event Graph->Update Animation,这样可以获得更高的性能

image

注意:后续函数都需要勾选线程安全

image

  • 获取旋转

image

  • 获取速度

image

image

  • 获取加速度
  1. 先创建获取角色运动组件的函数,返回值命名为ReturnValue,并勾选纯函数

image

这样就可以在属性存取中直接使用了

  1. 获取加速度

image

image

  • 更新获取所有数据

image

此时完成动画转换逻辑,需要填补动画序列,Lyra中进行解耦

  1. 创建动画层接口ALI_AnimationLayerInterface,定义需要的动画

image

此时没有具体实现

  1. 创建蓝图ABP_ItemLayerBase实现ALI_AnimationLayerInterface接口,角色蓝图ABP_LyraCharacter也实现该接口

为了方便解耦,这里定义动画序列变量, 对应输出姿势

image

  1. 再创建子蓝图ABP_PistolLayers继承ABP_ItemLayers,并在类默认值中指定具体的动画片段,实现绑定

image

  1. 最后将角色蓝图ABP_LyraCharacterABP_PistolLayers链接到一起

打开角色蓝图类BP_LyraCharacter,新建动画层

image

此时就可以播放动画了,但是动画带位移,并在位移后回溯

  1. 设置根运动

过滤所有的MF Pistol动画序列右键->属性矩阵,勾选RootMotion下的启用根运动强制根锁定

image

距离匹配

为了让运动的距离,和动画的距离保持一致,需要用到Locomotion Library插件(用于为动画生成距离曲线)

Start, Cycle, Stop都需要进行距离匹配

距离匹配在ABP_ItemLayerBase中实现

Start

替换为序列求值器, 显示时间即为动画显示的帧,需要动态指定,以匹配距离

image

  • Setup Start Anim

初始化显示时间为0

image

  • Update Start Anim

需要进行距离匹配,使用Advance Time by Distance Matching

image

参数说明:
Distance Traveled: 上一帧移动的距离

在动画蓝图ABP_LyraCharacter中获取

image

Distance Curve Name: 动画距离曲线的名称

需要使用Locomotion Library插件,先添加DistanceCurveModifier

image

删除原本的距离曲线

image

添加新的距离曲线,这里命名为Distance

image

ABP_ItemLayersBase中将Distance Curve Name提取成变量,并赋值Distance

Cycle

因为移动是循环动画,动画时间无限长,所以根据显示时间进行距离匹配不太合理,需要基于速度进行匹配

这里使用的是动画播放器,并添加Update Cycle Anim函数即可

image

  • Update Cycle Anim

使用函数Set Playrate to Match Speed即可

image

参数说明:
Speed To Match: 上一帧的移动速度,基于Update Start Anim->Distance Traveled进行计算,也是在ABP_LyraCharacter中计算,并存取

image

Stop

image

  • Setup Stop Anim

image

  • Update Stop Anim

分两种情况,如果急停,需要距离匹配;否则直接加速结束动画。

image

急停情况,通过Predict Ground Movement Stop Location预测角色停止位置,然后用Distance Match To Target来让动画匹配停止点

image

停止情况,直接加速播放动画即可

image

曲线压缩设置

此时游戏运行,输出日志会有很多黄色警告,说未使用统一索引编码

先打开一个动画,找到曲线压缩设置,并索引过去,然后复制一份,重命名并设置为UniformIndexableAnimCurveCompressionSettings

image

image

image

然后全选所有MF的动画序列,属性矩阵修改,设置Compression->曲线压缩设置都为UniformIndexableAnimCurveCompressionSettingsCtrl+S保存,然后回到UniformIndexableAnimCurveCompressionSettings中点击压缩即可

步幅适配

游戏人物的速度不是一成不变的,速度快时需要步幅变大,速度小时需要步幅减小;

在动画蓝图ABP_ItemLayersBase中做修改

  • Start
    image

  • Cycle

Start相同

image

同步组

为了保持动画切换时,左右脚能够保持一致,也需要用到Locomotion Library插件

  1. 设置StartCycle动画播放器/动画求值器同步组

image

  1. 然后打开StartCycle使用的动画序列,添加SyncMarkerAnimModifier修饰符并应用

image

image

8向移动

四向移动

获取速度的方向信息

  1. ABP_LyraCharacter中创建函数Update Cardinal Direction From Velocity,类别为方向
  • 计算速度角度

image

  • 根据速度的方向角,设置方向的枚举
  1. 创建蓝图->枚举, EAnimCardinalDirections

image

  1. ABP_LyraCharacter创建一个函数Select Cardinal Direction From Angle(纯函数+线程安全),类别为工具函数

设置输入,最后一个类型是刚建的枚举

image

image

image

image

向前向后的Dead Zone乘上2,是为了让玩家更容易进入向前和向后的状态

image

image

image

image

  1. 回到Update Cardinal Direction From Velocity函数中,调用Select Cardinal Direction from Angle

需要参数:
Dead Zone: 默认值10,提升为变量Dead Zone

Use Current Direction: 取决于上一帧是否有速度,有则使用,无则不用
在函数Update Velocity中计算得到

image

image

  1. 添加到Blueprint Thread Safe Update Animation

image

  1. 创建结构来代表所有动画,蓝图->结构SAnimCardinalDirections

image

  1. Start, Cycle, Stop需要方向适配

7.1 Start

image

  • Setup Start Anim

image

7.2 Cycle

  • Update Cycle Anim

image

image

7.3 Stop

image

  • Setup Stop Anim

image

  1. 打开ABP_PistolLayers

添加对应动画

image

  1. 给其他的StartCycle动画添加同步组标记

此时运行存在问题
10. 打开Character Movement->旋转朝向移动取消勾选类默认值->用控制器控制Yaw勾选

  1. Left Start动画起步会滑步,这是由于该动画起步前摇太长,需要处理,截取前五帧即可

朝向扭曲,实现八向

  1. 前面完成了4向移动,后面通过添加朝向扭曲,实现八向

12.1 ABP_ItemLayersBase->FullBody_Start

image

image

12.2 FullBody_Cycle 与上同理

朝向扭曲在前,跨步扭曲在后

回转运动

向左启动时,突然又向右启动,这时Start其实只切换了一次,所以会出现滑步

回转动画本身有两部分:当前方向的急停动画+反方向的加速动画

  1. 先修改ABP_LyraCharacter中的动画状态机

image
24.cnblogs.com/blog/1537983/202401/1537983-20240122172750777-1595182968.png)

  • Pivot Sources->Pivot

只要加速度速度不同向,则需要回转

image

  • Pivot->Cycle

回转动画播放到匀速运动时通知切换,动画中添加通知(第4节),创建蓝图类继承自AnimNotifyState,命名为ANS_ToLocomotion

切换状态

image

  1. ALI_AnimitionLayerInterce添加FullBody_Pivot动画层,在ABP_LyraCharacter中返回这个动画层姿势

image

  1. ABP_ItemLayersBase实现Full Body Pivot层接口,创建状态机

之所以创建状态机,而不是单个动画,原因:在Pivot过程中又反向运动,会导致无法重新进入该状态,即回转运动只能进行一次,没法叠加执行

image

image

3.1. PivotA状态

image

  • 绑定函数Setup Pivot Anim
  1. 需要根据加速度方向决定用哪个回转动画

ABP_CharacterBase中创建函数Update Cardinal Direction From Acceleration

image

这里不需要参数Use Current DirectionCurrent Direction,只有在判断前后移动时需要扩大Dead Zone死区

由于加速度当前速度方向不一致,所以加速度的方向应该取反,创建纯函数Get Oppisite Direction

image

最后添加到Brintprint Thread Safe Update Animation

image

  1. 回到ABP_ItemLayersBase,根据Direction From Acceleration决定使用序列

image

  • Update Pivot Anim进行距离匹配

image

2.1. Stop阶段距离匹配,利用Predict Ground Movement (Pivot) LocationDistance Match To Target

image

2.2. Start阶段距离匹配,使用Advance Time By Distance Matching

image
24.cnblogs.com/blog/1537983/202401/1537983-20240122174520717-2018213814.png)

  1. 跨步扭曲朝向扭曲加入进来

image

3.2 Pivot B状态

复制一份Pivot A,然后考虑到Pivot APivot B的转换条件,应该是加速度方向改变

所以需要记录上一帧的加速度方向,在Pivot A->Setup Pivot Anim中补充代码

image

然后确定状态转换条件

image

image

  1. ABP_PistolLayers中设置动画,并添加动画通知,添加同步标记

image

image

  1. Pivot APivot B设置同步组

ABP_ItemLayersBase序列求值器->细节设置

image

  1. 解决垂直移动问题

目前回转运动只能解决一条直线上的运动,如果在左右回转时,立马施加垂直向前的运动,则会边回转动画边前向移动

ABP_LyraCharacter中创建函数Update Is Moving Perpendicular to Initial Pivot,用于判断当前运动方向初始运动方向是否一致

  • 初始运动方向获取

动画状态机->Pivot输出姿势->变为相关时->创建绑定, 命名为Setup Pivot State

变为相关时,记录一次当前的速度方向,记为Pivot Start Direction From Velocity

image

  • 判断是否垂直,结果记为Is Moving Perpendicular to Initial Pivot

Pivot Start Direction前后,而当前速度``不是前后则认为垂直;左右同理

image

  1. Update Is Moving Perpendicular to Initial Pivot添加到Blueprint Thread Safe Update Animation

image

  1. ABP_ItemLayersBase中补充Pivot A->Pivot B的转换条件,即当垂直时不要过渡到回转,而直接过渡到Cycle

image

只有在动画的后半段通知后,才会过渡到Cycle动画,还是存中问题

  1. 提前过渡动画到Cycle

增加一个转换条件,设置原转换条件优先级为2,值小先检测

image

垂直移动了,则直接转换到Cycle

image

没有垂直移动,才根据动画通知转换

第一次Start右走,突然变换方向朝前,人物会往右看/右斜,原因是向前移动时,还在播放Start动画,没有及时转化到Cycle

  1. 添加转换条件,修改原条件优先顺序为2

image

10.1 在Start输出姿势,绑定函数Setup Start Anim,存储初始移动方向

image

image

10.2 如果当前方向和初始方向不一致,则提前转换到Cycle

image

原地转身 - 根旋转与胶囊旋转分离

让人物不随着鼠标而旋转,原理是:让根骨骼鼠标旋转相反,这样胶囊体在旋转而骨骼模型保持静止

  1. AnimGrgph中添加旋转根骨骼, 创建变量 Root Yaw Offset

image

  1. Update Rotation Data中获取两帧之间的旋转量Delta Rotation

image

image

  1. 创建函数Update Root Yaw Offset

    1. 创建枚举EAnimRootYawOffsetMode
    • Accumulate 逐渐累加Root旋转,与鼠标旋转抵消,用于Idle状态
    • HoldOn 保持现在的Root旋转,用于StartStop
    • BlendOut 逐渐减小Root旋转,让鼠标能够完全控制人物移动方向
      image
      创建变量Root Yaw Offset Mode
    1. 创建函数Set Root Yaw Offset
      image
      image
      image

    限制范围是为了避免:镜头正对着人物前方,然后人物Start时动画突兀

    image
    3. 分支处理不同情况
    image

    • Accumulate
      image
    • HoldOn 直接忽略,不作任何处理即可
    • BlendOut 插值到0
      image
    • 设置默认状态为BlendOut,大部分时候都是鼠标完全控制旋转
      image
  2. 设置Acculate状态,创建函数Update Idle State
    image

  3. 设置HoldOn状态,创建Update Start State函数绑定到Start动画的更新时

image

image

  1. 相同操作,用于Stop动画,函数Update Stop State

image

  1. 添加到Blueprint Thread Safe Update Animation中,注意Is First Update要放后面

image

  1. 需要更改Update Cardinal Direction From Velocity

视角转,但是人物移动方向没有转

image

这是由于计算World Rotation是用胶囊体旋转(视角旋转始终和胶囊体旋转一致),但是播放动画却是基于网格体朝向的,所以会出现人物要向前走,但实际动画是播放网格体朝向的向前走,出现不一致

所以在计算Local Velocity Angle时需要减去Root Yaw Root

image

image

人物动画和视角朝向不一致

image

这是由于朝向扭曲用的还是Local Velocity Angle,需要更改为Local Velocity Angle with Offset,涉及Start, Cycle, Pivot

image

视角与人物朝向偏差太大时,会先播放朝后启动动画,再转身Cycle,应该直接切换到Cycle

image

增加Start->Cycle转换条件,将优先级设置为1,混合时长设为1,其他两个增加1,当根偏移超过60度直接转换到Cycle

image

同时为了保证转身更自然,转换条件也设置同步组为Locomotion,会先走两步,脚部标记有衔接的时候才会过渡过去

image

混合有点突兀,把Start->Cycle的过渡时间设置为1

原地转身 - 原地转身

根旋转偏移限制在[-120,120]之间,超过了就会鼠标带动人物模型旋转

如果超过了偏移限制,则播放原地转身

  1. 修改ABP_ItemLayerBase中的FullBody Idle实现,将序列播放器先剪切

image

image

image

  1. 创建原地转身状态机,因为原地转身动画具有很长的后摇,转身过程中,如果视角又转动很大,则需要重新进入原地转身状态,所以这里也需要两个状态相互转换,所有转换都选择惯性化混合

image

  • Idle->Turn In Place Rotation & Turn In Place Recovery->Turn In Place Rotation
    image

  • Turn In Place Recovery->Idle
    image

  • Turn In Place Rotation->Turn In Place Recovery
    根据动画曲线判断,Lyra中找到TurnYawAnimModifier,右键在文件夹视图中显示->回退到Animations目录->右键AnimModifiers->迁移到当前项目的Content
    image
    image

  1. 创建Turn LeftTurn Right动画序列

  2. 添加Turn In Place Rotation动画播放器,添加变得相关时函数Setup Turn In Place Rotation

image

image

添加更新时函数Update Turn In Place Rotation

image

  1. 添加Turn In Place Recovery动画播放器,添加变得相关时函数Setup Turn In Place Recovery

绑定初始位置为4的上下文差量时间

image

  1. Turn In pLace Rotation->Setup Turn In Place Rotation需要根据旋转角度变化来决定是Turn Left还是Turn Right

    1. Turn In Place Rotation输出姿势,添加变得相关时绑定Setup Turn In Place Rotation State函数
      image
    2. 选择动画序列
      image
  2. Turn In Place Recovery动画选择同6
    创建Setup Turn In Place Recovery
    image

  3. ABP_PistolLayers中设置动画
    image

原地转身动画循环播放

原因是根旋转偏移并没有改变,所以会一直满足转换条件Idle->Turn In Place Rotation(偏移大于120度)
image

  1. 新建函数Process Turn Curve Value
    image

image

image

  1. Update Idle State中调用Process Turn Curve Value
    image

瞄准偏移

  1. 创建瞄准偏移动画->瞄准偏移,命名为MF_AO_Pistol

image

image

  1. 过滤所有的MF Pistol AO动画,属性矩阵修改为AdditiveSettings->网格体空间叠加

基础姿势动画MF_Pistol_Idle_ADS_AO_CC

image

局部空间 和 网格体空间 叠加对比

image

  1. MF_AO_Pistol中,左侧设置预览基础姿势,按住ctrl预览

image

  1. ALI_AnimLayerInterface中添加AimOffset层,设置输入参数

image

  1. ABP_LyraCharacter->AnimGraph

5.1 将接口添加到AnimGraph

image

5.2 接口需要输入的参数,需要安全更新,创建安全更新函数Update Aim Offset Data
image

5.3 添加到Blueprint Thread Safe Update Animation的末尾
image

  1. ABP_ItemLayersBase中实现AimOffset动画,将Blend Space公开引脚并提取成变量,在ABP_PistolLayers中赋值
    image

  2. 回到AimOffset实现层,给接口函数绑定参数
    image

跳跃着陆

  1. ABP_LyraCharacter中的Locomotion_SM,添加状态
    image

  2. 获取动画转换数据

    1. Update Character State Data, 添加到Blueprint Thread Safe Update Animation

    image

    image

    image

    image

    1. 更新跳到顶点的时间Update Jum Fall Data

    image

    image

    1. 计算掉落地面距离,(不要放到线程安全中,线程安全中只做更新,不做计算), Get Ground Distance,在事件蓝图更新函数中调用

    image

    image

  3. 添加动画转换条件

    1. Jump Sources->Jump Selector: 直接勾选
    2. Jump Selector: 勾选
    3. Jump Selector->Jump Start: Is Jumping
    4. Jump Selector->Jump Apex: Is Falling
    5. Jump Start->Jump Start Loop: 直接勾选基于序列...
    6. Jump Start Loop->Jump Apex: Jump Apex Time < 0.4
    7. Jump Apex->Fall Loop: 勾选基于序列...
    8. Fall Loop->Fall Land: Ground Distance < 200
    9. Fall Land->End In Air & End In Air Source->End In Air: Is On Ground, 任何条约状态都可能直接接触地面
    10. End In Air: 勾选
    11. End In Air->Cycle Alias: ToStart共享规则,优先级1
    12. End In Air->Idle Alias: 勾选, 优先级2
  4. 动画部分

    1. ALI_AnimLayerInterface添加动画层

    image

    1. ABP_LyraCharacter中将所有动画层->姿态输出

    2. ABP_ItemLayerBase

    • 创建动画序列变量

    image

    • 动画序列变量通过序列播放器输出姿势, 涉及Fall Loop, Jump Apex, Jump Start Loop, Jump Start

    • Fall Land使用序列求值器来距离匹配

    image

    变为相关时创建绑定函数Setup Fall Land Anim

    image

    更新时创建绑定函数Update Fall Land Anim

    image

    生成动画距离曲线

    image

  5. 修改动画资源,过滤Jump动画序列,属性矩阵操作

启动根运动强制根锁定, 曲线压缩设置->Uniform...->打开Uniform...文件点击压缩

  1. ABP_Pistol动画赋值

看向镜头

Link动画层切换

转身移动-控制绑定套用

转身移动的简易实现方法