Skip to main content

VRM-Animation 导出

请参考实装的 BVH Converter 

  • menu - VRM1 - Experimental - Convert BVH to VRM-Animation...

Assets/VRM10/Editor/VrmAnimationMenu.cs

说明

输入

为了导出 VrmAnimation,需要以下条件:

  • 符合 humanoid 规范的游戏对象 hierarchy(层级) 结构。
  • 确保人体模型的 hierarchy(层级) 结构处于 T-Pose 状态。
  • 随着时间的推移,humanoid 的层级结构姿态会发生变化。

为了简单地达到以上条件,我们使用了bvh 格式文件。

警告:
如果 BVH 的初始姿势不是 T-Pose,将无法正常工作。

UNITY HUMANOID 不是必须的
使用 Animator.GetBoneTransform 会更简单。

初始化

VRM Animation exporter 使用说明
Transform humanoid_hierarchy;

var data = new ExportingGltfData();
using var exporter = new VrmAnimationExporter(
            data, new GltfExportSettings());
exporter.Prepare(humanoid_hierarchy.gameObject);

VRM Animation exporter 使用说明
exporter.Export((VrmAnimationExporter vrma) =>
{
    // get human bones
    var map = new Dictionary<HumanBodyBones, Transform>();
    var animator = bvh.Root.GetComponent<Animator>();
    foreach (HumanBodyBones bone in Enum.GetValues(typeof(HumanBodyBones)))
    {
        if (bone == HumanBodyBones.LastBone)
        {
            continue;
        }
        var t = animator.GetBoneTransform(bone);
        if (t == null)
        {
            continue;
        }
        map.Add(bone, t);
    }

    vrma.SetPositionBoneAndParent(map[HumanBodyBones.Hips], bvh.Root.transform);

    foreach (var kv in map)
    {
        var vrmBone = Vrm10HumanoidBoneSpecification.ConvertFromUnityBone(kv.Key);
        var parent = GetParentBone(map, vrmBone) ?? bvh.Root.transform;
        vrma.AddRotationBoneAndParent(kv.Key, kv.Value, parent);
    }

推进时间并注册帧

// get animation
    var animation = bvh.Root.gameObject.GetComponent<Animation>();
    var clip = animation.clip;
    var state = animation[clip.name];

    var time = default(TimeSpan);
    for (int i = 0; i < bvh.Bvh.FrameCount; ++i, time += bvh.Bvh.FrameTime)
    {
        state.time = (float)time.TotalSeconds;
        animation.Sample();
        vrma.AddFrame(time);
    }

输出

});
var glb =  data.ToGlbBytes();

提示
这是在通常的 glb 基础上添加了 VRMC_vrm_animation 的版本