
做游戏的人迟早都要面对这个经典问题Maya里摆得好好的模型、场景、动画一进UE要么是躺着的要么是歪的要么干脆朝向全乱。说这是“运气问题”就太天真了本质原因是Maya和UE用了两套完全不同的坐标系。这篇文章我把这个事的底层原理、日常导入导出流程、以及不依赖FBX的脚本转换方法一次说清楚适合刚入行的技术美术、DCC工具链开发以及被资产朝向折腾到想摔鼠标的环境美术。Maya是右手坐标系、Y轴向上UE是左手坐标系、Z轴向上。光看这句话可能觉得没什么但真正做项目的时候“手性”“轴向”“旋转顺序”这三个词会在你导入蒙皮、摄像机动画、点云数据、程序化生成结果时反复出现。下面按我实际在项目里的处理顺序来写。1. 先搞清楚两套坐标系的关系——一个右手一个左手1.1 轴向差异Maya的Y-Up和UE的Z-UpMaya默认的轴向是X向右、Y向上、Z朝向屏幕外。听起来很直观因为美术在正视图里画东西Y轴向上符合直觉。UE则不同它规定Z轴向上X轴向前Y轴向右。你可以把UE理解成一个“地图平面高度”的组合X和Y是地面上的前后左右Z是高度。这个差异意味着同一个“朝上”的概念在Maya里是Y轴方向在UE里是Z轴方向。所以模型从Maya导出到UE如果不做任何转换模型相当于在Maya里是站立着的但在UE里会沿着X轴方向躺倒。你可以这样记Maya的“上”是UE的“前”Maya的“前”是UE的“右”……不对前面的细节值得展开讲。1.2 坐标映射关系从六个方向推出来先把两套轴向完整列出来以角色模型的标准摆放位置为参考Maya轴向含义UE对应轴向含义X右Y右-X左-Y左Y上Z上-Y下-Z下Z前X前-Z后-X后从表格能直接写出坐标值转换关系P_ue (P_maya.z, P_maya.x, P_maya.y)也就是UE的X坐标取自Maya的Z坐标UE的Y坐标取自Maya的X坐标UE的Z坐标取自Maya的Y坐标。这里要特别提醒这个映射关系存在一个前提就是模型在Maya中按标准朝向摆放角色面朝Z。如果美术在Maya里把模型随便转了30度再导出那后面所有轴转换讨论都没有意义必须先让模型回到标准朝向再谈导出。我在项目里见过太多次“坐标转换怎么算都不对”的案例最后发现是模型本身没有正对Z轴。还有一点容易被忽略这个变换矩阵的行列式是正的意味着它是个纯旋转不包含镜像。这很重要因为镜像变换会导致法线翻转、模型里外反转而Maya转UE不会出现这个问题通常也不需要你手动去翻转法线。2. 常规资产导入把轴转换交给FBX2.1 FBX为什么能自动处理一次说透大多数情况你不需要自己写坐标映射因为FBX格式本身保存了轴系统信息。FBX文件的GlobalSettings里记录了它来自哪个DCC、UpAxis是哪根轴、FrontAxis是哪根轴。UE在导入FBX时会读取这些信息在内部自动把Y-up的数据旋转成Z-up。这就是为什么直接拖一个FBX进UE模型通常是站立且朝向正确的。你把FBX理解成一个带“元数据”的快递盒Maya那边发货时写清楚了原产地坐标规则UE收货时就会自动拆包并把货物摆正。自己写转换脚本只是兜底方案通常用在上游数据不是FBX或者你需要批量操作点数据的时候。2.2 Maya导出设置实测清单Maya导出FBX时以下几个地方建议固定下来不要每回都凭感觉勾选单位Window Settings/Preferences Preferences Settings Working Units Linear必须设为Centimeter。UE内部默认单位也是厘米如果Maya里用了Meters或者Inches导入UE后物体会整体缩放100倍或者缩成原来的1/100。导出命令直接File Export All或者Export Selection导出对话框里选择FBX格式。Axis ConversionFBX导出设置的Advanced Options Axis Conversion通常不需要额外改保持默认的Y-Up就行。这里默认值会让Maya生成的FBX记录“Up Axis Y”UE导入时会自动转换成Z-up。勾选Smoothing Groups对硬表面模型尤其重要不勾选的话导入UE后圆滑组会乱掉模型会变得“棱角分明”。勾选Tangents and Binormals如果做的是需要法线贴图的资产建议导出切线。不导出的话UE会自己计算切线某些接缝位置容易出现光影瑕疵。动画相关如果需要导出动画确保Bake Animation勾选并把Resample All Curves选上避免导入UE后曲线抖动。2.3 UE导入设置怎么做最省心UE导入FBX时弹出的FBX Import Options里有几点保持默认通常就好Import Translation / Import Rotation / Import Uniform Scale全部留0/0/1。UE会自己处理Y-up转Z-up你再加旋转反而会转错。Normal Import Method默认的Import Normals and Tangents即可。如果模型法线有问题再考虑改成Compute Normals。Import Mesh默认勾选。如果导入的是骨骼模型记得在Animation选项卡里选好Skeleton并确认Root Bone设置。我自己踩过的坑是美术好心在Maya里把模型整体旋转了90度想“提前调整好”结果导出后UE又转了一次模型歪了45度。这里统一规则比“好心”重要。2.4 导入后朝向还是不对从这三个地方找原因如果你严格按照上面流程做了导入UE后模型朝向依然不对优先排查这三项Maya场景里模型是否正对Z轴。选中模型查看Translate和Rotate如果Rotate不是0先执行Modify Freeze Transformations冻结变换后再导出。FBX导出对话框的Axis Conversion是否被改成了Z-Up。有人为了让FBX“适配UE”手动把Up Axis从Y改成了Z结果UE导入时又转一次模型反而躺倒。UE导入选项里的Import Rotation是否被填了数值。有时候美术或策划为了“临时修正”在导入选项里加了旋转下次重导又会叠加建议一律清0。检查完这三项90%的朝向问题都能解掉。3. 不依赖FBX的硬核转换Python脚本批量操作3.1 什么时候需要自己写转换FBX虽然好用但遇到下面这些场景你就必须自己动手了手里是CSV或TXT点云文件里面有几千个点的坐标要摆到UE场景里。你从Maya里导出的是自定义数据格式比如JSON或者XML引擎端要直接读取。你是程序化生成管线在Maya里用Python生成了一批物件坐标想直接生成UE蓝图放置数据。你要把Maya里的灯光位置、摄像机位置批量导出给UE不想走FBX。有人可能会说“FBX也能干这些事啊”确实能但FBX解析起来麻烦而且为了几个坐标点去走一整套DCC导出链路效率太低了。自己用Python算一遍映射十分钟搞定。3.2 Maya端CSV坐标转换脚本下面这段脚本可以直接在Maya的Script Editor里跑作用是把一份Maya坐标CSV转换成UE坐标CSV。假设输入文件每一行是x,y,z三个值没有表头。import csv def maya_csv_to_ue_csv(input_path, output_path): rows [] with open(input_path, r) as f: reader csv.reader(f) for row in reader: if not row or len(row) 3: continue mx float(row[0]) my float(row[1]) mz float(row[2]) # 核心映射UE_X Maya_Z, UE_Y Maya_X, UE_Z Maya_Y ux mz uy mx uz my rows.append([ux, uy, uz]) with open(output_path, w, newline) as f: writer csv.writer(f) writer.writerow([UE_X, UE_Y, UE_Z]) writer.writerows(rows) # 用法示例 maya_csv_to_ue_csv(D:/maya_points.csv, D:/ue_points.csv)这个脚本很简单但确实验证过可以跑。核心就是那一行坐标映射如果你项目中角色朝向习惯和其他项目不一样需要先确认真实的映射表别想当然用我给的公式。建议先拿一个已知的点测试Maya里放一个坐标(100, 200, 300)的物体转换出来应该在UE里是(300, 100, 200)然后在UE里手动验证。如果你希望支持带表头的CSV或者每行数据里还有名称、旋转、缩放自己扩展一行解析逻辑就行。批量处理大文件时建议每处理1000行打印一条进度方便知道脚本卡没卡。3.3 反向转换与旋转数据的处理反向转换就是从UE坐标转回Maya公式是逆映射P_maya (P_ue.y, P_ue.z, P_ue.x)逻辑很好理解Maya的X取UE的YMaya的Y取UE的ZMaya的Z取UE的X。旋转数据比位置麻烦得多。坐标点很好转因为只是三个轴的置换旋转则涉及旋转顺序。Maya默认的欧拉旋转顺序是XYZ而UE内部旋转是Yaw(Pitch(Roll)对应的是ZYX顺序。如果你尝试直接把Maya里的欧拉角拷贝到UE里几乎必然结果不对。正确做法是把Maya欧拉角转成旋转矩阵用坐标映射矩阵做一次相似变换再按UE的旋转顺序分解出Yaw/Pitch/Roll。示意代码如下import numpy as np from scipy.spatial.transform import Rotation as R def maya_euler_to_ue_euler(mx_deg, my_deg, mz_deg, maya_orderxyz): # Maya欧拉角 - 旋转矩阵 r_maya R.from_euler(maya_order, [mx_deg, my_deg, mz_deg], degreesTrue) # 坐标映射矩阵 M np.array([ [0, 0, 1], [1, 0, 0], [0, 1, 0] ]) # 相似变换R_ue M * R_maya * M^T r_ue R.from_matrix(M r_maya.as_matrix() M.T) # 按UE的ZYX顺序输出 Yaw/Pitch/Roll yaw, pitch, roll r_ue.as_euler(zyx, degreesTrue) return yaw, pitch, roll这段代码依赖numpy和scipy实际Maya环境里不一定有但你完全可以用Maya自带的OpenMaya矩阵类来实现同样的逻辑。核心思想就是用矩阵做中间转换层别试图硬凑三个欧拉角。我在项目里遇到过有人直接用“旋转轴对调”的方式转旋转值比如Maya的rx转成UE的pitchry转成yawrz转成roll结果模型角度全乱。这不是数学不好是对旋转顺序没有敬畏。所有涉及旋转的人为转换一律走矩阵不要手动对应轴向。3.4 批量摆放数据的实战用法这个脚本最常见的用途是批量生成UE场景摆放数据。比如你有一个Maya场景里面手动摆了几百棵树的位置现在要把这些树在UE里以相同位置放置。做法是导出CSV位置信息用脚本转成UE坐标然后在UE里用HISMHierarchical Instanced Static Mesh组件批量生成实例或者用Python在编辑器脚本里循环SpawnActor。我实际做过的流程是这样在Maya里选中所有树模型用Python脚本输出每个模型的translate到CSV。运行上面的转换脚本得到UE坐标CSV。在UE编辑器里写一个Editor Utility Widget读取CSV遍历每一行在对应坐标点SpawnActor。检查发现有几棵树位置在地面以下原因是Maya里树的轴心点没有统一有的轴心在根部有的在模型中心。归根结底还是资产规范问题不是坐标转换能解决的。所以脚本解决的是“坐标系不一致”的问题资产轴心和命名规范还是要靠流程来管。4. 进阶场景骨骼、动画与相机4.1 角色骨骼与动画的坐标陷阱FBX导入角色骨骼时UE会自动处理骨骼整体的Y-up到Z-up旋转骨骼树内部的层级关系会被保留。所以大部分情况下角色不需要额外做骨骼坐标转换。但有几个容易出问题的点Root Bone根骨骼朝向。UE的Humanoid Rig要求骨骼T-Pose时角色面朝X但在Maya里标准姿势是面朝Z。FBX导入通常能处理这个差异但前提是Maya里的绑定朝向是规范的如果骨骼节点在Maya里被旋转过导入UE后Root Bone可能带着一个额外角度导致动画重定向时整个角色偏移。肩部、手指这些旋转敏感的骨骼。骨骼如果自身带roll角比如肩部骨骼绕自身长轴转了30度导入UE后可能出现手腕扭曲。因为UE在计算骨骼空间时用的是全局旋转矩阵的逆分骨翻转顺序有细微差异。应对办法是在Maya绑定阶段就保持骨骼轴向与世界轴对齐别为了刷权重方便随便旋转骨骼。动画曲线采样。导出动画时勾选Resample All Curves避免Maya与UE的旋转插值算法差异导致角色动作抖动。4.2 旋转顺序为什么拷贝欧拉角会乱这一节值得单独拿出来说。MAYA和UE旋转顺序的差异是“为什么我手动算的旋转导入后总是错”的核心原因之一。Maya属性编辑器里有个Rotation Order参数默认是XYZ即先绕X轴转再绕Y轴转最后绕Z轴转。UE那边Actor旋转的Roll绕X、Pitch绕Y、Yaw绕Z但内部组合顺序是Yaw优先也就是ZYX。这正好和Maya默认顺序相反。如果你把Maya里的欧拉角原封不动导给UE等于用一个顺序去解释另一套顺序的结果角度自然错得离谱。典型的错误是Maya里只要不是三个轴都有旋转看起来好像还行一旦同时有多个轴旋转角色就会歪成奇怪的角度。解决办法还是那句用矩阵转换。搞一个工具脚本用户输入Maya欧拉角和旋转顺序输出UE的Yaw/Pitch/Roll所有转换都通过矩阵不手动映射轴向。这样既能在一次性转换任务里用也能沉淀成团队工具。4.3 相机与镜头动画的特殊处理相机是另一个重灾区。Maya相机的默认视线方向是自身局部坐标的-Z方向而UE的相机默认看向自身局部坐标的X方向。两套方向不仅差90度还有一个手性差异所以直接把Maya相机动画烘焙到FBX导入UE镜头经常扭成螺旋。我推荐的做法是在Maya里建一个“转换相机层次”把目标相机放在一个父级组下在父级组上套用一个坐标转换矩阵导出时只烘焙转换后的子相机这样动画曲线在源端就已经变成UE视角。另一种方案是直接不依赖通用FBX在UE里用虚拟摄像机工具Virtual Camera重新拍一遍反而更可控。如果只是要镜头路径的Position数据那简单坐标映射直接用第一节的公式就行但要带旋转就必须用4.2的矩阵转换思路。记住位置可以人肉算旋转一定要走矩阵。5. 常见问题速查与项目规范建议5.1 高频问题排查表问题现象常见原因解决思路模型导入UE后躺倒/歪斜Maya里模型Rotate未冻结或FBX导出Axis Conversion被改成Z-Up在Maya里利用Freeze Transformations导出保持Y-Up模型背面全黑自定义格式导入时三角形顶点缠绕顺序翻转检查导入设置Normal Import Method或交换顶点索引顺序角色骨骼动画扭曲Maya动画曲线未Bake或骨骼自带非标roll角导出时勾选Bake Animation和Resample All Curves检查骨骼轴向手动计算旋转值但结果全错忽略旋转顺序直接对调轴向通过旋转矩阵相似变换不要直接替换欧拉角xyzCSV点云摆放位置镜像颠倒坐标映射公式用反或用成镜像拿一个已知点(100,200,300)实测验证映射方向导入UE后物体大小不对Maya工作单位不是厘米检查Working Units Linear统一设为Centimeter这些坑几乎每个项目都会踩一遍。特别是“背面全黑”这个问题用FBX通常不会遇到因为FBX内部把缠绕方向处理掉了一旦你绕开FBX走自定义格式就要自己处理。5.2 建立项目规范从源头减少坐标系问题坐标系的坑靠人情提醒是堵不住的必须靠规范和工具。这里分享几条我沉淀下来的经验明确规定Maya资产标准朝向角色面朝Z场景地面在Y0平面。这条写进项目Wiki新人入职第一课就灌输这个意识。统一单位。Maya工作单位、FBX导出单位、UE项目单位全部用厘米。用代码在Maya启动时自动检查Working Units不对就报错。把坐标转换脚本封装成工具。Maya里做成工具架按钮UE里做成Editor Utility Widget一键导出/导入CSV降低手算出错概率。写一个“资产体检”Maya脚本一键检查模型是否面朝Z、是否冻结变换、是否非等比缩放、工作单位是否厘米。任何资产导出前必跑一遍。不要手动在UE导入选项里添加额外旋转或缩放所有修正必须在Maya侧完成。临时在UE里改导入参数资产更新后十有八九会叠错。我在实际项目里最深的一个体会是坐标转换本身并不难难的是所有环节的人都能遵循同一套规范。工具脚本能把“需要思考”变成“一键执行”这才是它最大的价值。如果你现在正被Maya和UE的坐标系折腾先别急着硬记公式把第一节的轴向映射表贴在工位上再用一个已知点验证一遍自己的理解后面所有环节都会顺很多。