Lyra动画系统-框架

Lyra动画系统框架

Lyra的动画系统框架很值得学习,他的核心思想就是解耦,不断地解耦。

主动画蓝图(ABP_Mannequin_Base) 用来实现最基础的状态机,其中每个状态都 没有具体实现,而是直接交给一个动画图层实现,这些动画层又被全部抽象出来,放在一个 动画层接口(ALI_ItemAnimLayers) 中,主动画蓝图继承这个动画层接口,但是也不实现这些动画层,把实现的工作交给另一个动画蓝图;把基础状态机和每个具体状态的实现解耦

状态实现蓝图(ABP_ItemAnimLayersBase) 也继承自动画层接口,用来实现每个动画层,但是实现时也不会直接把动画序列放进去,而是用序列播放器搭配动画序列变量,完成实现逻辑;把播放的动画序列和状态的实现解耦

资产配置蓝图(ABP_PistolAnimLayers) 继承自状态实现蓝图,负责把对应的动画序列填入状态实现蓝图的对应变量中:

最后,使用 关联动画类图层(LinkAnimClassLayer) 节点,把要要播放的资产配置蓝图和主动画蓝图关联即可;

Lyra这样设计动画系统可以非常方便的完成一个新状态机的制作,比如有使用手枪和使用步枪的两套动画,他们有相同的动画状态机和状态实现,只需要不同的资产配置蓝图用来把两套动画序列配置好即可,在切换武器时变更动画也非常方便。

动画节点与动画节点函数

在动画蓝图中,AnimNode是诸多节点的父类,从动画播放器(SequencePlayer)到动画状态机,都是动画节点。

动画节点函数

动画节点都可以绑定动画节点函数,按照函数的触发事件分为三种:

  1. On Initial Update:在该动画节点所属的AnimBP的生命周期中第一次执行节点时
  2. On Become Relevant:节点变为相关时,也就是每次开始执行节点时
  3. On Update:节点tick更新时

执行顺序是先执行上层的节点再执行下层的节点,如下图,先执行State节点,再执行序列求值器节点:

多线程更新动画(Blueprint Thread Safe Update Functions)

Lyra把原本放在 事件图标(EventGraph) 也就是游戏线程中执行的逻辑(比如获取角色的速度旋转等信息),放到了 工作线程 中执行,可以获得更好的性能。

但是这样做有个点要注意,由于将数据更新放在工作线程中,许多变量和函数无法直接调用(只有用BlueprintThreadSafe修饰的才可以),因为其他线程可能同时运行并且它们可能正在更改该数据。因此,使用 属性访问系统(Property Access System) 来访问数据。属性访问系统会在安全时自动复制数据:

为此,我们需要定义一系列函数来更新变量,这些函数需要勾选 线程安全 才能在BlueprintThreadSafeUpdateAnimation中被调用:

序列播放器(SequencePlayer)和序列求值器(SequenceEvaluator)

二者都是用来播放动画序列的动画节点,但序列播放器可以自动播放动画序列,序列求值器需要指出显式时间才能播放对应时间的动画帧;也就是说序列求值器更加灵活,常常将序列求值器播放的序列显式时间设为动态值,通过节点函数动态改变动画序列和播放速率:

Animation Layer Interface(ALI)

动画层接口是只能用在动画蓝图中的一个接口类,继承自UInterface;和蓝图接口一样,可以在其中创建函数,这些函数被称作AnimationLayers;实现这些函数的方法有:

  1. 继承了ALI的动画蓝图可以在其内部直接实现
  2. 运行时动态指定另一个继承了相同ALI的动画蓝图来实现(使用**关联动画类图层(Link Anim Class Layer)**),Lyra中就是这种方式;

Animation Layer

动画层也是一种动画蓝图,一种 子动画蓝图,本质是一种函数,不过函数处理和输出的都是动画数据;

  1. AnimLayer:在当前动画蓝图类中直接创建的
  2. LinkedAnimLayer:继承ALI后获得的

参考

【UE】Lyra动画系统拆解(框架篇)
UE5 白话Lyra动画系统


Lyra动画系统-框架
https://kenny-hoho.github.io/2023/12/20/Lyra动画系统复现-框架/
作者
Kenny-hoho
发布于
2023年12月20日
许可协议