UE4角色动画原理简介
UE4的角色动画采用了目前最流行的骨骼动画系统。骨骼动画系统大致可以分为两步:
- 计算骨骼Pose:每一根骨骼可以看做一个点,而我们的Pose就是所有骨骼Transform(位移+旋转+缩放)的集合,注意,一般来说,这个Pose是基于骨架参考姿势(Reference Pose)的变换矩阵。
- 蒙皮:骨骼计算好后我们还是无法看到一个角色的造型,这时需要将3D美术制作好的网格体的顶点按照骨骼Pose进行变化。这里变换的依据是顶点的蒙皮权重和参考姿势的信息(一个顶点可能受到多个骨骼的影响)。
动画系统更新过程简述
那么UE4里主要承担这两步职责的是Skeletal Mesh Component
。SkeletalMeshComponent
继承自SkinnedMeshComponent
。在SkeletalMeshComponent
创建时,会创建一个Animation Instance
,这就是主要负责计算最终Pose的对象,而我们制作的AnimationBlueprint
也是基于UAnimationInstance
这个类的。
在SkeletalMeshComponent
进行Tick时,会调用TickAnimation
方法,然后会调用Animation Instance
的UpdateAnimation()
方法,此方法会调用一遍所有动画蓝图中连接的节点的Update_AnyThread()
方法,用来更新所有节点的状态。
然后后续根据设置的不同会从Tick函数或者Work线程中调用SkeletalMeshComponent
的RefreshBoneTransforms()
方法,此方法进而会调用动画蓝图所有节点的Evaluate_AnyThread()
方法(注:部分节点类型此方法可能被屏蔽,后续拓展动画节点时会进行说明)。
Evaluate
的含义就是指根据特定的条件(从Update
时获得的参数)计算出动画所有骨骼的Transform信息,最后输出一个Pose给到渲染线程并存在本地Component上。
关于多线程
大家也许注意到了为什么在Evaluate和Update后面都有一个AnyThread
呢?原因是UE4的动画系统支持多线程的处理,一般来说Game线程会触发一系列Game Play逻辑,最后调用到动画系统的Update
内,然后这个方法里面把所有动画系统所需要的信息收集起来,存到一个Proxy里,然后计算具体Pose的工作就交给工作线程去完成,这时主线程可以继续进行后续的处理工作。需要注意的是,虽然此时Game线程未被Pose计算阻塞,但是渲染线程会等待RefreshBoneTransform
结束后再开始工作,如果Evaluate Pose的时候有很多高消耗的操作,会发现渲染线程的时间会增长。