在虚幻中复用表情动画

在虚幻引擎中复用表情动画

在虚幻引擎中,骨骼动画可以通过重定向资产在不同骨骼之间共用。基于 Morph Target 的表情动画同样可以复用,但具体做法因目标模型而异。

本文着重讨论 ARKit 表情动画的复用,但介绍的方法同样适用于任意 Morph Target 动画。

准备工作

首先,我们通过道乐师 MONO 录制一段表情动画,并将其导入虚幻引擎。将道乐师的 FBX 文件导入虚幻可以参见这里的注意事项

导入完成后,打开该动画资产,可以看到其中包含了基于 ARKit 标准的动画 Curve 数据。

ARKit 动画 Curve 数据
导入后的动画资产中包含基于 ARKit 标准的 Curve 数据

要将这段动画应用到新模型上,具体做法取决于目标模型的 Morph Target 配置情况。

1. 目标模型拥有同名 Morph Target

比如下面这个 Ready Player Me 模型,就带有以 Apple 的命名标准建立的全套 ARKit Morph Target。

Ready Player Me 模型的 ARKit Morph Target
Content Examples 中的 Ready Player Me 模型包含完整的 ARKit Morph Target

这种情况比较简单。只需打开目标模型的 Skeleton 资产,在 Window 菜单中选择 Asset Details。

打开 Skeleton Asset Details 面板
在 Skeleton 编辑器中通过 Window 菜单打开 Asset Details 面板

在弹出的面板中找到 Compatible Skeletons 一栏,将道乐师表情动画对应的骨骼添加进去即可。

添加兼容骨骼
在 Compatible Skeletons 中添加道乐师动画使用的骨骼

完成后,为目标模型创建一个动画蓝图。此时在资产浏览器中就可以看到道乐师导出的动画了。

动画蓝图中的道乐师动画
在动画蓝图的 Asset Browser 中可以看到道乐师导出的动画序列

将这个动画连接到输出节点后,你可能会发现模型突然变大或朝向改变。

模型变形问题
直接播放动画后模型出现变形,体积增大且朝向异常

这是因为道乐师表情动画的 Root 骨骼自带旋转信息,且 Scale 不为 1。播放动画时,这些数据也会被应用到最终的骨骼姿态上,导致模型整体发生形变。

Root 骨骼的旋转和缩放
道乐师动画的 Root 骨骼带有 90° 旋转和非标准 Scale 值

解决方法是在动画蓝图中使用 Layered Blend per Bone 节点。将表情动画作为 Base Pose 输入,Blend Poses 0 留空。同时,在该节点的 Layer Setup 下的 Branch Filters 中添加目标模型的根骨骼,这个 Ready Player Me 模型的根骨骼名为 Hips。

Layered Blend per Bone 节点设置
使用 Layered Blend per Bone 节点,在 Branch Filters 中指定根骨骼 Hips

这个节点的作用是,对于 Hips 及其子骨骼,使用 Blend Poses 0 的输入,由于留空,模型会保持原始骨骼姿态。对于 Curve 等其他通道,则使用 Base Pose 的输入,也就是表情动画数据。这样,骨骼的位置和缩放不受影响,表情 Curve 数据却能正常传递。

2. 目标模型没有同名 Morph Target,但提供了 Pose Asset

MetaHuman 是这种情况的典型案例。虽然它不直接包含 ARKit 同名的 Morph Target,但提供了 Pose Asset,可以实现从 ARKit Curve 到面部 Pose 的映射。

MetaHuman 的 Pose Asset
MetaHuman 的 Pose Asset 定义了 ARKit Curve 名称与面部 Pose 的对应关系

操作步骤与第 1 节类似。在 MetaHuman 的 Skeleton 中添加道乐师骨骼为兼容骨骼,然后就可以在 MetaHuman 的动画蓝图中播放道乐师的表情动画。

不同之处在于,需要在动画节点后面额外接入一个 Evaluate Pose 节点,并在其 Pose Asset 属性中选择 MetaHuman 自带的 ARKit 映射资产 PA_MetaHuman_ARKit_Mapping。这样,输入的 Morph Target 曲线就能正确转换为 MetaHuman 的面部 Pose。

MetaHuman 动画蓝图中的 Evaluate Pose 节点
在动画蓝图中通过 Evaluate Pose 节点将 ARKit Curve 映射为 MetaHuman 面部表情

3. 目标模型既没有同名 Morph Target,也没有 Pose Asset

比如下面这个 Daz 模型,它的 Morph Target 使用了与 Apple ARKit 完全不同的命名方式,比如 Jaw_Open 而非 jawOpenEye_Blink_Left 而非 eyeBlinkLeft

Daz 模型的 Morph Target 列表
Daz 模型使用了与 ARKit 不同的 Morph Target 命名规范

这种情况需要借助我们开源的重定向工具。

github.com/SunnyViewTech/UE-MorphTarget-Retargeting-Tools

这是一个 Python 脚本,运行后会按映射文件把源动画中的 Morph Target 曲线重命名,输出一个新的动画序列,直接拖到目标模型上就能用。

打开脚本后,需要配置以下几个关键参数。

SOURCE_ANIM_PATH  = "/Game/Capture.Capture"
MAPPING_FILE_PATH = "C:/arkit_mapping.txt"
TARGET_MESH_PATH  = "/Game/MyHead.MyHead"

SOURCE_ANIM_PATH 是源动画序列的资产路径。在内容浏览器中右键点击动画序列,选择 Copy Object Path 即可获取。

复制动画序列的 Object Path
右键动画序列,选择 Copy Object Path 获取资产路径

MAPPING_FILE_PATH 是 Morph Target 映射文件的本地路径。映射文件为纯文本格式,每行两列,左列为源动画中的 ARKit 名称,右列为目标模型中对应的 Morph Target 名称。

Morph Target 映射文件示例
映射文件将 ARKit 标准名称映射到 Daz 模型的命名,左列为源名称,右列为目标名称

TARGET_MESH_PATH 是目标模型的资产路径,同样通过右键 Copy Object Path 获取。

参数填写完毕后,在虚幻编辑器的 Tools 菜单下选择 Execute Python Script,然后选中该脚本执行。

执行 Python 脚本
通过 Tools > Execute Python Script 运行重定向脚本

运行完成后,会在指定目录下生成一个新的动画序列资产。打开可以看到,其中的 Curve 名称已经按照映射文件转换为目标模型的命名规范,可以直接在目标模型上播放。

生成的重定向动画序列
生成的动画序列中的 Curve 已按目标模型的命名规范重新映射

关于一对多的 Morph Target 映射

在实际项目中,有时会遇到源动画中的一个 Morph Target 需要同时驱动目标模型中多个 Morph Target 的情况。例如,源动画中的 jawOpen 可能需要同时驱动目标模型的 jawOpentongue_jawOpen 两个变形目标。

目标模型中的多个 jaw 相关 Morph Target
目标模型中 jawOpen 和 tongue_jawOpen 是两个独立的 Morph Target

处理方法很简单,只需在映射文件中为同一个源名称编写多行记录即可。工具会自动识别重复项,并将同一条 Curve 数据复制到所有对应的目标通道上。

一对多映射文件示例
在映射文件中为 jawOpen 添加多行记录,即可实现一对多映射

如果你在实际操作中遇到问题,欢迎通过 GitHub 仓库 提交 Issue,或访问 道乐师文档站 获取更多技术指南。