找回密码
 立即注册
查看: 300|回复: 0

UE5 动画同步组

[复制链接]
发表于 2023-1-23 09:42 | 显示全部楼层 |阅读模式
一、AnimSync的使用
AnimSync即动画同步组,用来解决动画切换融合过程中由于脚步差异国道导致的跳变,例如从一个结束帧为左脚在前的行走动画Pose融入到一个起始帧为右脚在前的动画Pose时,有于两个Pose差异过大,会出现Pose的突变,影响动画表现。
使用AnimSync可以解决这个问题,AnimSync会通过在动画中配置SyncMarker标记动画中的左右脚,在实际播放时,将会根据当前正在播放的同一组,决定动画的融入融出帧,实现的更好的动画融合表现。
1.设置同步组

在动画蓝图中,所有用来播放动画资产的Player动画节点都可以在Details中配置SyncGroup相关的参数




GroupName:同步组的命名,用来创建同步组或者指定动画所属的同步组,所有使用相同GroupName的动画播放节点属于同一个同步组,例如,通常在行走动画或跑步动画的动画播放节点中会设置相同的同步组。
GroupRole:在动画同步过程中的角色,分为两种角色,Leader作为动画同步主体,Follower动画会向根据Leader动画调整自身的播放时间,在同步过程中,通常会根据动画融合的权重决定GroupRole。


Method:同步的方式,Do not Sync不参与同步,SyncGroup根据GroupName对动画进行分组,同一组内的动画进行同步,Graph配合Sync动画节点和BlendSpaceGraph使用,Sync需要配置GroupName,会将所有SourcePose中使用Graph同步方式的动画播放节点合并到Sync节点指定的Group,BlendSpaceGraph也需要提供GroupName,同步方式与Sync动画节点相同。






Montage中也可以配置SyncGroup的相关参数,
Sync Group:填入同步组的名字
SyncSlotIndex:参与同步的动画Slot索引


需要注意,Montage只在融出时参与同步,并且默认是Leader,即其他正在播放的动画会向Montage同步。
2.添加SyncMarker

SyncMarker通常用来标记行走动画中脚步的位置,在Sequence中添加,SyncMarker通常为一对,分别用来指示动画播放中左右脚落地的位置


添加方式如下


在添加SyncMarker时通常会对齐左右脚落地的时刻,例如L代表左脚落地,R代表右脚落地。可以采用其他的时刻对齐,基本要求是SyncMarker的位置能够反映动画的节奏。
手动添加SyncMarker无法做到精确对齐,工作量也比较大,可以通过Animation Modifier将这部分自动化。
二、主要数据结构

FAnimGroupInstance: SyncGroup实例,包含当前帧需要同步的动画播放记录、GroupLeader、当前组中的SyncMarker等数据。
FAnimTickRecord:记录当前正在播放的动画资产的相关信息,包含动画资产实例、已播放时长、FMarkerTickRecord、混合权重等数据,
FMarkerTickContext: 记录一次Tick前后的SyncMarker的前后位置
FMarkerTickRecord:记录当前播放位置的前后SyncMarker
FMarkerSyncAnimPosition:记录当前动画的播放位置在前后两个SyncMarker之间的相对位置,相对位置会在0-1之间
包含AnimSync相关方法的函数集,实际处理动画同步,成员变量SyncGroupMap是一个读写分开的双buffer数据结构,存储所有的FAnimGroupInstance
FAnimAssetTickContext:记录动作Tick时重要的相关数据。
三、AssetPlayer的SyncGroup处理

动画模块每帧的更新通常分为两部分,Update和Evaluate,Update部分由GameThread完成,Evaluate会分配在异步的工作线程。
Update会计算当前动画资产播放的具体时间,Evaluate部分会根据当前动画的播放时间提取出相应的Pose。
AnimSync通过调整同组内动画资产的播放时间,完成同步,所以由动画的Update部分触发,在GameThread执行。
动画蓝图中的SequencePlayer、BlendSpacePlayer等AssetPlayer播放动画时,AssetPlayer中的AnimSync执行方式基本相同,每帧执行,分为两部分构成。
第一部分的入口在AsssetPlayer中的UpdateAssetPlayer方法,构建FAnimTickRecord,记录当前帧播放的动画资产、是否循环播放、播放速度、混合权重等数据,随后调用FAnimSync::AddTickRecord。
此时计算每个动画资产的LeaderScore,每个同步组中LeaderScore最高的正在播放的动画为Leader,其余动画为Follower,对于除了Montage之外的普通动画资产,例如Sequence、BlendSpace等,会根据预先配置的AnimGroupRole计算LeaderScore,共有5中Role,AlwaysLeader的LeaderScore为2.0,AlwaysFollower、TransitionFollower始终为0,CanBeLeader、TransitionLeader为当前动画播放的权重,即会随动画播放的过程而变化。
完成FAnimTickRecord的创建,根据AssetPlayer中配置的GroupName,找到FAnimSync中对应的FAnimGroupInstance,将FAnimTickRecord交由FAnimGroupInstance管理。
总结一下,第一部分根据AssetPlayer的动画播放状态做数据准备,以FAnimGroupInstance为单位存放,供第二部分执行使用。
第二部分的入口为FAnimSync::TickAssetPlayerInstances,由AnimInstance Update调用,此时会便利所有的FAnimGroupInstance,如果Group中有至少一个正在播放的动画,则对其进行同步处理。
FAnimGroupInstance会对当前组中的动画根据LeaderScore进行排序,最终组内的动画会按照LeaderScore得分从大到小排列,对当前组中动画的SyncMarker进行过滤,移除无效的SyncMarker,留下只符合当前AnimSync需要的SyncMarker。
此时默认同步组内第一个动画为GroupLeader,执行动画资产的TickAssetPlayer方法,对于GroupLeader动画来说,TickByMarkerAsLeader执行具体的逻辑,当前动画播放时间不会受到影响,在前一帧动画播放时间加上此次DeltaTime,得出最新的动画播放时间,同时更新FMarkerTickContext中记录的前后两个SyncMarker之间的Sync位置,如果由于两个SyncMarker之间当前的相对位置无法得到新的有效相对位置,则将同步组内LeaderScore第二高的动画作为GroupLeader执行上述步骤,依次顺延,直到完成FMarkerSyncAnimPosition位置的更新。
找到有效的GroupLeader后,同步组内其他的动画会作为Follower处理,依旧调用动画资产的TickAssetPlayer方法,TickByMarkerAsFollower执行具体的逻辑,Follower会根据当前Tick中FMarkerTickContext记录的两个SyncMarker之间的位置,找到配置在Follower动画中最匹配当前SyncMarkerPosition的前后SyncMarker,通过等比例计算,得到当前Follower动画的播放时间。
四、Montage中的SyncGroup处理

Montage的特殊之处在于,Montage的播放必须严格执行,即在同步组中只可为Leader,不可为Follower,此外Montage参与同步只会在其播放完毕即将混出时发生。
Montage的AnimSync分为两部分执行,第一部分入口为UAnimInstance::UpdateMontageSyncGroup,当MontageInstance已经停止播放正处于动画混出阶段并且MontageInstance拥有有效的GroupName时,创建FAnimTickRecord,封装MontageInstance的播放数据,交由FAnimSync管理。
第二部分入口经FAnimSync::TickAssetPlayerInstances调用至UAnimMontage::TickAssetPlayer,所有Montage的LeaderScore默认为3.0,此时默认作为Leader进行处理,实际动画时间不会受影响,只是会根据Montage的播放时更新FMarkerTickContext中记录的SyncPosition,用于其他Follower动画进行同步。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-6-23 09:33 , Processed in 0.089158 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表