ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

揭秘 Unity 到 Maya 的坐标系转换:Unity-Runtime-Animation-Recorder 的四元数转欧拉角原理

揭秘 Unity 到 Maya 的坐标系转换:Unity-Runtime-Animation-Recorder 的四元数转欧拉角原理 揭秘 Unity 到 Maya 的坐标系转换Unity-Runtime-Animation-Recorder 的四元数转欧拉角原理【免费下载链接】Unity-Runtime-Animation-RecorderRecord animations in Unity runtime. Can save to .anim, maya, or FBX ASCII format.项目地址: https://gitcode.com/gh_mirrors/un/Unity-Runtime-Animation-RecorderUnity-Runtime-Animation-Recorder 是一款 Unity 运行时动画录制工具能在 Play 模式下逐帧抓取场景中所有 Transform 的运动数据并一键导出为 .anim、Maya .ma 或 FBX ASCII 文件。它的核心难点在于Unity 到 Maya 的坐标系转换与四元数转欧拉角算法——搞懂了这两点你就明白了为什么导出到 Maya 后旋转不会“翻车”。为什么 Unity 的动画不能直接喂给 MayaUnity 与 Maya 使用不同的 3D 坐标约定属性UnityMaya手性左手坐标系右手坐标系向上轴Y 轴Y 轴朝向前进Z-Z旋转描述四元数Quaternion欧拉角rotateX/Y/Z两者 Y 轴一致但 X/Z 的方向关系完全不同而且旋转的存储格式也不同。如果不做转换模型会镜像翻转、旋转方向倒转。转换逻辑集中封装在一个小工具类里ExportHelper.cs路径Unity Runtime Recorder/Scripts/General/ExportHelper.cs。位置转换只需翻转 X 轴位置转换极其简单一行代码搞定public static Vector3 UnityToMayaPosition (Vector3 t) { return new Vector3(-t.x, t.y, t.z); }因为两软件 Y 轴都是向上的镜像发生在水平面内——X 取负即可把“左手 X 朝右”映射到“右手 X 朝左”而 Z 轴数值恰好保持不变。旋转转换四元数转欧拉角的关键一步Unity 内部用四元数存旋转避免万向节死锁而 Maya 的animCurveTA曲线需要的是三个欧拉角且必须按X → Y → Z的顺序展开。转换入口只有两行public static Vector3 UnityToMayaRotation (Quaternion q) { // x,y,z is Mayas rotation order // and due to right hand / left hand coordinate, y z should *-1 return WikiQuaternionToRotation(q, new Vector3(1,-1,-1)); }注意最后的Vector3(1,-1,-1)欧拉角算出来后Y 轴和 Z 轴角度分别乘以 -1这是补偿左右手坐标系差异的“点睛之笔”。四元数是怎么一步步变成欧拉角的核心函数 WikiQuaternionToRotation 参考了维基百科“四元数与欧拉角互转”页面的 Python 示例用三组解析公式分别求出绕 X、Y、Z 轴旋转的角度z, y, x绕 X 轴rollx atan2(2(w·x y·z), 1 - 2(x² y²))绕 Y 轴pitchy asin(2(w·y - z·x))绕 Z 轴yawz atan2(2(w·z x·y), 1 - 2(y² z²))其中 w、x、y、z 是四元数localRotation的四个分量。三个结果统一乘以Mathf.Rad2Deg换算成度。这个实现里藏着两个容易被忽略的工程细节asin 的数值安全浮点误差可能让2(wy - zx)略微超出[-1, 1]直接传给asin会得到 NaN。代码里用if (t2 1) t2 1; else if (t2 -1) t2 -1;做了钳制保证任何姿态都能算出合法角度。atan2 而非 atanX/Z 两轴用Atan2(t0, t1)计算天然覆盖四个象限不会出现 180° 跳变歧义。记录流程逐帧四元数如何写入 .ma 文件整条数据链非常清晰理解它比背公式更重要录制TransformTracker.recordFrame()路径Unity Runtime Recorder/Scripts/General/TransformTracker.cs在每帧LateUpdate中把localRotation四元数存入rotDataList同时抓取localPosition和localScale。转换MayaNodeDataContainer.WriteIntoFile()路径Unity Runtime Recorder/Scripts/MayaExporter/MayaNodeDataContainer.cs逐帧调用ExportHelper.UnityToMayaPosition和ExportHelper.UnityToMayaRotation把每帧数据变成 X/Y/Z 三列数值。拼装每根轴生成一个 Maya 动画曲线节点形如createNode animCurveTA -n 节点名_rotateX; setAttr .tan 18; setAttr -s N .ktv[0:N-1] 0 角度0 1 角度1 ...; connectAttr 节点名_rotateX.o 节点名.rx;ktv数组就是“帧号 欧拉角”序列connectAttr把曲线输出接到节点的rx/ry/rz属性上——这就是 .ma 文件里旋转动画的本质。别忘了 Joint Orient脚本的自动“排雷”导出 Humanoid 骨骼时Maya 关节还有个 Unity 没有的Joint OrientMaya 中的实际旋转 Transform 旋转 Joint Orient。直接导入会导致脊柱动画叠加错误。MayaAnimationRecorder.cs路径Unity Runtime Recorder/Scripts/MayaExporter/MayaAnimationRecorder.cs的exportToMayaAnimation()用一条正则把原 .ma 文件里所有.jo -type double3值批量替换为0 0 0自动解决了这个坑——你在 Unity 录完就能直接得到可播放的骨骼动画。FBX ASCII 导出复用同一套转换项目里的 FBX 导出器Unity Runtime Recorder/Scripts/FbxExporter/FbxExporter.cs没有另写一份算法而是直接复用ExportHelper.UnityToMayaPosition与ExportHelper.UnityToMayaRotation把同样的转换结果写进 FBX ASCII 的动画曲线节点中。这也解释了文档中的一条要求源 FBX 文件必须是 ASCII 格式因为脚本是通过文本方式把animCurve数据拼接到文件里的。上手体验三步录出可导出的 Maya 动画把Unity Runtime Recorder文件夹拷入 Unity 工程的 Assets想体验完整效果可一并拷贝DemoAssets其中DemoAssets/Scenes/ExportToMayaAnimation.unity就是 Maya 导出演示场景。给任意 GameObject 挂上MayaAnimationRecorder.cs在 Inspector 中用 Select MA File 选择包含模型的 .ma 源文件Save File To 指定输出路径。进入 Play 模式按下 Q 开始、W 结束按键可在 Inspector 自定义。结束时脚本自动逐帧转换四元数、写曲线、合并文件最终得到一份带动画的 .ma 文件。常见问题速查导出的旋转为什么会镜像确认没有绕过UnityToMayaRotation而直接写入原始四元数展开结果——Y/Z 乘 -1 这一步不能省。某帧角度变成 NaN那就是asin输入超域了务必保留[-1, 1]钳制逻辑。pitch 接近 ±90° 时 X/Z 角度会“乱跳”吗会这是欧拉角万向节死锁的固有现象属于角度表示法的数学特性录制端用四元数存储、导出端才转欧拉角已把误差控制在导出时刻。导出量大时卡顿勾选 Record Limited Frames 限制帧数或调整Time.timeScale减速模拟。小结Unity-Runtime-Animation-Recorder 用一个不足百行的 ExportHelper.cs 解决了跨软件动画导出的两大痛点X 轴镜像的位置转换与带左右手补偿的四元数转欧拉角。它的算法思路——逐帧记录四元数、导出时解析展开、用atan2/asin加钳制保安全——对任何想打通 Unity 与 Maya、Blender 等 DCC 工具链动画通道的开发者都是可直接借鉴的范本。【免费下载链接】Unity-Runtime-Animation-RecorderRecord animations in Unity runtime. Can save to .anim, maya, or FBX ASCII format.项目地址: https://gitcode.com/gh_mirrors/un/Unity-Runtime-Animation-Recorder创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表