Coder Social home page Coder Social logo

lyratutorial's Introduction

Lyra动画蓝图制作

原版视频

官方文档

基础移动

新建动画蓝图 ABP_CharacterBase

基础移动

基础移动状态机

为了让基础移动状态机能够实现状态切换,需要在各个状态之间添加状态转移条件

例如:从IdelMoveStart,需要判断角色的加速度是否大于0

BlueprintThreadSafeUpdateAnimation 线程安全更新数据函数

为了获取角色数据,常规做法是从动画蓝图中的Event Blueprint Update Animation中获得通过Try Get Pawn Owner获得角色对象,进而获取角色数据(该Event每帧执行)

Lyra中,使用函数重载中的Blueprint Thread Safe Update Animation(蓝图线程安全更新动画),这个函数在最前面官方文档中提到过

在为你的角色类开发动画时,需要注意一些做法,以确保你的动画以最佳性能运行。在Lyra中,我们使用多线程动画来计算动画值,而不是使用事件图表。

点击 BlueprintThreadSafeUpdateAnimation 函数,你可以查看负责收集动画数据和处理这类计算的函数。

使用线程安全函数时,你无法像在事件图表(Event Graph)中那样直接从游戏对象访问数据。例如,如果你尝试为角色的速度复制Gameplay浮点值,则此操作不会被视为线程安全,因此我们建议使用属性访问(Property Access)来就这些情况进行调整。

Lyra中的使用

在Lyra的动画蓝图中,对该函数有明确的注释信息

这个函数主要负责收集游戏数据,并将其处理为选择和驱动动画的有用信息
现场安全函数的一个注意事项是:我们不能像在事件图表中那样直接访问游戏对象的数据。这是因为其他线程在同一时间可能正在改变这些数据。相反,我们使用属性访问系统来访问数据。在安全的情况下,属性访问系统会自动复制数据。

Property Access的使用

一般来说,不会直接在BlueprintThreadSafeUpdateAnimation中编写更新代码,而是调用更新函数(美观)

基本示例

如何向Property Access中添加一些自定义属性呢?

基本示例

对比上图中的左右两边,发现我们自定义的GetMovementComponent纯函数被添加进了Property Access中去了

重点:返回值参数名得是ReturnValue,纯函数,线程安全

共享条件

就是一些相同的判断条件,不需要重复书写,通过Promote To Shared来共享判断条件

比如:从IdelMoveStart是判断是否存在加速度,从MoveStopMoveStart也是判断是否存在加速度,此时这个判断条件就可以共享

基本示例

UE还贴心的用相同的颜色去区分不同的共享条件

基本示例

当该动画播放完毕之后会自动跳转到下一个状态

动画层接口

新建动画层接口 ALI_AnimLayerInterface

动画层接口

如图新建动画层接口

设置接口

在动画蓝图中实现动画层接口

设置接口

给各个状态设置 连上对应的动画层接口 动画

新建专门用来实现动画逻辑的动画蓝图

新建一个动画蓝图ABP_ItemLayerBase,专门用于实现动画逻辑:动画的动态切换、动画的动态选择、距离匹配等逻辑

与之前创建的ABP_CharacterBase相同,使用相同的骨骼,并且也实现ALI_AnimLayerInterface动画层接口

而这个动画蓝图不需要实现状态机,只需要专注于动画层即可

设置接口

通过变量和bind的方式,将Sequence Player节点的值与变量绑定,以后修改只需要修改变量默认值即可,无需求改任何节点

同理,对其他三个接口也是相同的操作,定义Anim Sequence变量,绑定到Sequence Player

注意 StartStop 两个状态的Sequence Player需要关闭动画循环(默认开启)

此时,基类定义完毕,接下来要做的就是用刚刚新建的ABP_ItemLayerBase作为基类,定义真正设置值的子类

比如,这里新建一个ABP_PistolLayers子类,表示持手枪的一个动画蓝图

设置动画资源

打开之后,右下角可以直接进行动画资源的设置

关联动画类图层

这里新建一个Character,设置 Sekeletal Mesh Component的骨骼,动画蓝图为前面创建的ABP_CharacterBase

此时状态机已经在跑了,但是动态机各个状态只设置了从接口输出动画,并没有设置各个接口的动画资源;动画层蓝图设置了实现了各个接口输出的动画资源,并没有状态机

因此只需要将 ABP_CharacterBaseABP_PistolLayers关联起来即可

关联动画蓝图和动画层

使用Link Anim Class Layers节点,绑定动画蓝图和动画层

距离匹配

角色移动的时候,脚步与移速并不可能完美对齐

会使用插件Animation Locomotion Library中的一些函数节点

首先是,动画才需要距离匹配,所以需要关注的文件就是ABP_ItemLayerBase,这个文件中定义了动作节点会输出的动作文件

然后就是需要确定哪些动作需要做步幅匹配,比如 Start、Stop、Cycle 三个动作就是做步幅匹配的

Start 起跑动画

应用序列求值器

这里使用序列求值器来做步幅匹配,重点为显式时间,也就是Explicit Time,可以用来控制动画当前行进进度

应用序列求值器

需要注意的就是,这个SetupStartAnim函数是绑定在变为相关时触发,也就是状态机行进到该状态时,所以此时需要将显式时间设置为0,从头开始播放动画

如果不在进入状态时将显式时间设置为0,则该动画就不是从头播放,而是从上次做计算时设置的显式时间开始,在当前环境下这是个很明显的错误

应用序列求值器

然后就是后续更新时绑定函数UpdateStartAnim

MoveStart为例,角色是逐渐加速,直到进入行走循环的过程

有一个节点Advance Time by Distance Matching 根据位移去计算一个显式时间,在Lyra这个项目的ABP_ItemAnimLayersBase中相同位置的Update函数对该函数有一段注释

AnimBP Tour #9
This is an example of using Distance Matching to ensure that the distance traveled by the Start animation matches the distance traveled by the Pawn owner. This prevents foot sliding by keeping the animation and the motion model in sync.
This effectively controls the play rate of the Start animation. We clamp the effective play rate to prevent the animation from playing too slowly or too quickly.
If the effective play rate is clamped, we will still see some sliding. To fix this, we use Stride Warping later to adjust the pose to correct for the remaining difference.
The Animation Locomotion Library plugin is required to have access to Distance Matching functions.

机翻结果为:

这是一个使用 "Distance Matching" 确保 "Start" 动画移动的距离与典当所有者移动的距离相匹配的示例。这可以通过保持动画和运动模型同步来防止脚滑动。
这可以有效地控制“开始”动画的播放速率。我们限制有效播放速率,以防止动画播放过慢或过快。
如果有效播放速率被限制,我们仍然会看到一些滑动。为了解决这个问题,我们稍后使用“步幅扭曲”来调整姿势,以纠正剩余的差异。
动画运动库插件需要访问距离匹配功能。

Advance Time by Distance Matching

通过上图可以看到Advance Time by Distance Matching的几个参数,前两个可以直接获得,第三个Distance Traveled每帧位移,这个位移需要到基础动画蓝图,也就是ABP_CharacterBase中去计算,并且将值封装到Property Access这种线程安全的获取方式中

ABP_CharacterBase中新增线程安全函数UpdateLocationData,新增变量WorldLocation记录上一帧坐标,新增变量DisplacementSinceLastUpdate计算距离变化,新增变量bIsFirstUpdate用于判断是否是第一次计算(初始值为true)

UpdateLocationData

随后记得把UpdateLocationData函数添加到Blueprint Thread Safe Update Animation中,并将bIsFirstUpdate设置为false

UpdateLocationData

此时我们通过UpdateLocationData函数计算得到了DisplacementSinceLastUpdate变量,接下来就是编写 纯函数、线程安全、返回值参数名为RetureValue 的获取该值的函数

不过跟上面获得移动组件的PropertyAccess函数不同,由于这个DisplacementSinceLastUpdate定义在ABP_CharacterBase中,但是使用却是在ABP_ItemLayerBase中,所以需要在ABP_ItemLayerBase中定义这样的获取函数

为了一劳永逸,直接定义获得动画蓝图的函数即可

动画层中获得动画蓝图

获得每帧位移

曲线名称是什么?

曲线名称

以官方提供的lyra动画MF_Pistol_Jog_Fwd_Start为例,下面的Gif图片展示了如何一键添加距离曲线,这个是插件提供的功能

曲线名称

曲线名称

那么Start起跑动画就做完了,接下来要做的就是Cycle跑动的循环动画

Cycle 跑步循环动画

起跑动画做距离匹配用的是动态调整动画显式时间的,但是循环跑动动画是不能通过调整显式时间来做距离匹配的,因为它是循环动画,去调整显式时间(播放进度)是没有意义的,所以针对循环动画要调整的是播放速率(Play Rate)

Cycle动态设置速率

Cycle动态设置速率

Cycle的播放速率与移动速度相关,所以老样子要在ABP_CharacterBase中添加移速相关的变量,方便ABP_ItemLayerBase获取

Cycle动态设置速率

在计算每帧位移的时候,也可以顺便计算每帧的移动速度,只需要使用位移除以DeltaTime即可

这里使用Safe Divide其实就是除以的意思
别忘了在Blueprint Thread Safe Update Animation函数中为UpdateLocationData传入DeltaTime参数

Cycle动态设置速率

Stop 停止动画

与Start状态部分相同,使用序列求值器(Sequence Evaluator)

设置Stop状态的序列求值器

同样要设置进入相关状态时,显式时间为0

设置进入Stop状态的初始化

然后就是处理Update函数了

什么时候要播放Stop动画?应该是有速度,但是没有加速度的情况

Stop状态的更新函数

  1. 首先就是是否播放Stop动画的判断:有速度(HasVelocity)和无加速度(HasAcceleration),两个参数封装在动画蓝图ABP_CharacterBase中,所以可以用前面定义的获得动画蓝图的Property Access获得

  2. 使用Predic Ground Movement Stop Location计算移动停止的坐标,该函数的参数都封装在MovementComponent中,所以需要写一个获得Character MovementProperty Access函数

  3. 这里获得的速度是上一帧计算得到的速度

  4. 这里额外判断的一下距离停止坐标的距离是否大于0,大于0才需要做距离匹配

  5. 当不需要做距离匹配的时候,直接将动画加速到结束即可(Play Rate = 1)

问题解决

通过上面的一系列操作,确实得到了一个基本满足距离匹配的动画蓝图

但是当打开output log,会发现很多的警告

动画警告

这个是因为动画的曲线压缩设置不匹配导致

动画警告

新建基类为Curve Compression Settings为基类的UniformIndexAnimCurveCompressionSettings文件,设置其CodecUniform Indexable

随后将所有的动画的曲线压缩设置替换为UniformIndexAnimCurveCompressionSettings

批量设置曲线压缩

Gif展示如何批量设置

动画警告

最后点击压缩即可,警告解决

步幅匹配

步幅匹配就是 移动速度越快,步子迈的越开;移动速度越慢,步子迈的越小

使用Stride Warping步幅扭曲节点来做步幅匹配

动画警告

随后将该节点在Start和Cycle中使用,Stop状态只做距离匹配一般就够了不用步幅匹配

可以在角色的Character Movement中设置最大移动速度观察不同的效果

最大移速为200时

200移速

最大移速为500时

500移速

同步组

为了让两个状态的动画能够平滑过度,需要引入同步组

这里的平滑过渡指的是左右脚匹配

这里以Start和Cycle为例

添加同步标记

使用SyncMarkerAnimModifier来自动添加左右脚的标记,需要给Start的动作和Cycle的动作都进行这样的标记处理

序列设置

StartCycle的序列都进行上图设置,GroupName必须相同

移动的八方向

传统做法:混合空间

Lyra做法:朝向扭曲OrienTation Warping

避免出现混合空间导致的脚与脚之间的交叉穿模,因为它是旋转扭曲整个下半身骨骼

动画蓝图中计算朝向

通过角色的朝向和速度可以计算出朝向与速度方向之间的角度

表示方向的枚举

获得速度方向与角色朝向之间角度

判断方向

记得把该函数放到BlueprintThreadSafeUpdateAnimation

把DeadZone提升为变量,方便配置

接下来便是编写通过角度判断前、后、左、右方向的工具函数SelectCardinalDirectionFromAngle

判断方向

通过Angle和DeadZone,可以区域判断,至于原因下图可知

45 + FwdDeadZone 可以确定超前的区间角度,135 - BwdDeadZone可以确定朝后的区间

判断完前后之后,判断左右就很快了,角度大于0就是右边,小于0就是坐标

动画层中配置动画

创建存储四方向的结构体

结构体

分析一下:目前有四个动作(start、idel、cycle、stop),其中需要考虑八方向的是start、cycle、stop,start和stop只需要在变为相关时处理,cycle需要在Update函数中处理

  • Start

首先就是让序列求值器的动画序列取消绑定,并设置为Dynamic动态值,输入的动画都是根据朝向动态设置的

然后就是在Start动画变为相关时的绑定函数中,根据动画蓝图计算的朝向,选择对应的动画资源

  • Cycle

同理,Cycle的动画序列也改为Dynamic

同理,Cycle动画序列的Update的绑定函数中,根据动画蓝图计算的朝向,选择对应的动画资源,不过这里要使用Set Sequence With Inertial Bledning来混合动画

一般在动画序列的Update绑定函数中使用 Set Sequence With Inertial Bledning来混合动画 在动画序列的 On Become Relevent 变为相关中直接使用 Set Sequence

  • Stop

同理,Stop的动画求值器中的Sequene资源也改为Dynamic

同理,Stop的动画也只用在变为相关中直接SetSequence根据动画蓝图计算的朝向,选择对应的动画资源即可


既然Stop、Cycle、Start的动画都从各自对应的朝向动画结构体中选取,那么MoveStart、MoveStop、MoveCycle三个变量也不需要了,可以直接删除

设置数据

设置持枪角色动画层资源

Character MovementOrient Rotation to Movement旋转朝向运行设置为false

在类默认设置中,将Use Controller Rotation Yaw用控制器旋转Yaw勾上

开始八方向扭曲

通过上面的操作,我们得到了四方向移动的动画,很明显是没有斜着移动的效果的

朝向扭曲用到Orientation Warping节点

然后分别在Start和Cycle中使用即可

这里还有一点就是Orientation Warping 一定要在 Stride Warping 之前使用,这个先后顺序不能错

lyratutorial's People

Contributors

nicetry12138 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.