1. 跨引擎资产搬运:为什么总有团队需要这种插件
1.1 一个做工具链的人每天面对的真实场景
先说说我自己遇到的情况。工作室做了两年多的UE原型项目,里面的白盒关卡、角色动画、材质资产已经积累到几十个G。后来因为发行和招聘等原因,项目整体转向Unity。听起来好像"都是引擎,导一下不就行了",实际上美术团队一听到这个消息,第一反应是"那不是全部要重做吗"。
我当时的任务就是把一套在UE里打磨了很久的资源,尽可能原样搬进Unity。你要知道,不是每个人都是双引擎都熟练的,美术同事对UE很熟,但到了Unity里连Asset Store都还没逛明白。这时候最怕的不是工作量本身,而是工作量根本无法预估。一个几百个资产的关卡,如果靠人肉导出再手动对齐材质,光是整理命名和检查坐标轴就能消耗掉一整个迭代周期。
这个系列聊了不少Unity插件,这篇要讲的Exporter for Unreal to Unity就是用来解决这个问题的:装到UE编辑器里,把网格、骨骼网格、动画、材质、纹理,甚至场景里Actor的摆放关系,按一套约定导出成Unity能直接吃进去的工程资产。它的价值不是"能导出一个FBX文件"——FBX谁都能导——而是在导出过程中把单位、坐标朝向、贴图命名、粗糙度翻转这些容易翻车的环节一次性处理掉。
1.2 直接拖原始资源文件进来为什么不行
你可能觉得奇怪,UE项目里本身就有FBX、OBJ这些源文件,Unity直接导入不就行了?理论上可以,但有两个非常现实的问题。
第一,源文件不一定还在。很多资源到了UE里之后,是在引擎内二次加工的:重新设置材质实例、合并碰撞体、调整LOD、挂载蓝图逻辑。这些信息不存在于原始FBX里,你拿原始文件进Unity,等于拿到了一个没有涂装、没有骨架绑定的半成品。
第二,UE和Unity之间不是简单的"格式兼容"问题。两者用了不同的世界坐标约定、不同的单位、不同的PBR材质参数组织方式。就算是一个干净的静态网格,直接把UE导出的FBX丢进Unity,你也会遇到模型躺倒、尺寸大了100倍、法线贴图看起来凹陷、粗糙度通道完全映射错位这类问题。一次两次可以手动修,但一百个资产、上千张贴图的时候,手动修就是一个灾难。
所以这套插件的核心思路,是把Conversion Logic做成自动化规则:导出时帮你把Z轴转Y轴、把厘米换算成米、把Roughness翻成Smoothness、把法线贴图绿色通道翻转、把贴图后缀改成Unity材质面板认识的命名。你在UE里点一下导出,Unity里看到的就已经是"本地原生"的样子了。
2. 这个插件能搬什么不能搬什么:功能边界盘点
2.1 支持的资源类型清单
我用过的这个版本,主要覆盖了这几类资源,基本对应了日常游戏资产的主流部分。
- 静态网格(Static Mesh):含顶点数据、UV、法线、切线、LOD层级。LOD0到LDOn会按顺序导出,方便Unity里重组LOD Group。
- 骨骼网格(Skeletal Mesh):包含骨骼层级、蒙皮权重,Unity里作为Generic或Humanoid导入都行,前提是骨骼命名不要被插件重写得太离谱。
- 动画序列(Anim Sequence):可以把选中的动画一次打包导出,保留骨骼动画的关键帧数据,Root Motion信息也能带出来。
- 材质与贴图:UE的材质参数会被梳理成PBR属性——BaseColor、Metallic、Roughness、Normal、AO、Emissive。导出的贴图自动套用Unity的命名规则。
- 碰撞体:静态网格上的简单碰撞和复杂碰撞(UCX开头的碰撞网格)会保留,Unity侧能自动认成Collider。
- 场景/关卡层级:导出整个关卡或选中Actor的集合时,位置、旋转、缩放父子关系都会保留,导入后生成一个Prefab或Scene层级。
这里想强调一点:网格和纹理的搬运只是基本功,真正省时间的其实是材质和碰撞体。美术最烦的就是在Unity里重新连一遍材质节点,插件能自动生成Standard/Lit着色器可用的贴图组合,至少把贴图通道全部接好,进Unity后只需要微调。
2.2 明确说明不支持的部分
任何工具都有边界,提前知道边界比看到宣传就盲目上要重要得多。
- 光照构建数据:UE的Lightmass烘焙结果、Volumetric、距离场阴影这些,均不能迁移。Unity里需要重新烘焙光照贴图和光照探头。
- Nanite网格:Nanite是UE5基于GPU驱动的虚拟几何体,没有传统意义的网格数据文件供导出。需要先烘焙成代理网格,否则拿不到可用的渲染网格。
- Niagara粒子系统:整套GPU/CPU粒子资产无法直接转,最多能导出发射器使用的网格和贴图,Unity里用VFX Graph或粒子系统重搭。
- Groom毛发:UE的毛发系统是独立资产,导出的是一堆曲线和控制数据,Unity原生不认。要用第三方毛发方案另算。
- 蓝图逻辑:这不是资源转换问题,而是运行时逻辑跨引擎重写问题。插件能搬运的是资产,不是程序。
2.3 导出的组织方式与命名约定
插件在处理大批量资产时的组织方式很关键,否则你导出几百个文件,Unity里还是乱成一锅粥。正常流程下,它会按你在UE里的目录层级,在目标文件夹里生成对应的子目录结构,模型文件按资源名命名,贴图文件带上后缀区分用途。
比如UE里一个箱子资产的贴图命名是Chest_BaseColor、Chest_Normal、Chest_Metallic、Chest_Roughness,到Unity里插件会转成Chest_Albedo、Chest_Normal、Chest_Metallic、Chest_Smoothness(注意Roughness已被反转成Smoothness)。这个命名规则正好匹配Unity的Standard着色器属性名,自动导入时材质能直接找到对应贴图,不用手动拖拽。
3. 实操链路:从UE侧导出到Unity侧导入的完整流程
3.1 安装与入口
插件实际是一个UE编辑器插件,安装方式和其他编辑器插件一致:从资源商店下载后,放到项目的Plugins目录下,或者在Epic启动器里启用,然后重启编辑器。注意要在项目设置里确认插件已被激活。
入口方面,不同版本的UI位置有差异,但我常用的版本是在编辑器的工具栏多了一个面板,左侧是资源浏览器,右侧是导出设置。你也可以选中一批资源后,通过右键菜单直接调出导出对话框,所见即所得,这比去找菜单层级要顺手得多。
3.2 UE侧导出设置
导出前我建议先做两步检查:确认目标Unity项目的版本和渲染管线(内置管线还是URP/HDRP),因为贴图导入设置和着色器兼容性会受影响;然后把所有要导出的资源从"引用状态"捋一遍,别漏掉被材质引用的贴图。
具体操作层面,插件面板里关键的几个选项我列一下,这是最容易让人困惑的地方:
- Export Path:要输出到Unity项目里的哪个目录,直接选取Assets下的一个子目录。
- Group by Folder:按UE里的目录结构生成子目录,建议勾上,资产多了以后好维护。
- Convert Unit:单位转换选项。让插件把厘米数据转成米数据,或者保留标记让Unity导入时自动缩放。我的建议是让插件做主动缩放,Unity侧导入设置就能保持默认的1倍缩放。
- Convert Coordinate:坐标轴转换。目标Y-up,处理好Z-up到Y-up的旋转。
- Flatten Hierarchy:只对场景层级导出有效。如果勾选,所有Actor会压平成同一层级,适合只需要摆放结果不关心结构的情况;不勾选则保留父子关系。
这些选项每台机器第一次使用时会遇到理解成本,但调好一次以后基本都是记忆里的固定设置。我自己习惯保存一套默认配置,导出前只需要选资源和目标路径。
还有一个很多人忽视的点:动画导出时要注意帧率的设置。UE里动画可能是30帧也可能是60帧,建议固定导出帧率与实际项目一致。否则Unity里播放动画会给人一种微妙的"卡一下"的感觉,其实是采样点对不齐。
3.3 Unity侧导入设置
工作流设计得比较好时,Unity侧的导入几乎是全自动的。Unity会把插件生成的.fbx和贴图文件一起导进来:FBX导入后在模型导入器里往往已经带好了正确的缩放和轴转换(如果插件没有主动转,就需要手动在Model Importer里调整Scale Factor和Up Axis)。
贴图导入方面有个重要细节:颜色空间。BaseColor贴图应是sRGB,而Normal、Metallic、Smoothness这类数据贴图必须标记为Linear,否则渲染会过亮或过暗。插件一般会按Unity的命名后缀自动设置好纹理类型和颜色空间。自动设置没生效时,就需要在贴图导入器逐一勾选Normal Map和sRGB,几百张贴图的情况确实辛苦,所以插件这个自动标记功能真的能省大把时间。
3.4 导入后的资产重组
资源进入Unity后还不是终点,因为有好多约束体现在"工程使用层面"。
静态网格基本可以立即可用,但你要手动装配Collider:Unity会自动识别带UCX_前缀的碰撞网格并生成Mesh Collider,这个体验很不错。骨骼模型导入后,如果要做人形动画重定向,需要在Rig选项卡里把骨骼映射到Humanoid骨骼,这一步依赖骨骼命名,UE导出的骨骼命名如果和Unity默认映射表匹配度不够,就要手工调整。
最后一步是材质检查。在Unity里打开材质面板,确认Albedo、Metallic、Smoothness、Normal Map、Occlusion、Emission都已映射好。URP/HDRP下可能需要把Shader换成Lit或对应管线Shader。我习惯把所有导入资产的材质Shader先统一替换一次,替掉Standard,避免后期漏改一个就黑一片。
4. 坐标旋转、单位换算、粗糙度翻转:这套插件背后的转换逻辑
4.1 为什么UE和Unity不能直接共用FBX
两款引擎的渲染与数学体系存在根本差异,导致一个干净的FBX也无法直接通用。
UE使用左手坐标系,且世界向上轴是Z轴;Unity也是左手坐标系,但世界向上轴是Y轴。两者对"上"的约定不同,导致不加处理地把模型导入Unity,竖着的墙会变成躺着的墙。最简单的验证方式:在UE里导出一个立方体,直接导入Unity,你会发现它绕X轴旋转了-90度。这不是引擎Bug,而是坐标系的固有差异。
因此所有跨引擎管道,要么在导出时手动旋转根节点,要么在导入时设置Up Axis。真正的工程实践里,最稳妥的做法是导出一个"轴转换好的FBX",让Unity导入时不做额外Bake Axis Conversion,这样可以避免Unity侧的额外顶点变换,对大批量有性能意义。
4.2 单位换算:厘米与米的坑
单位问题比坐标问题更隐蔽,而且一旦错了,模型会大得离谱或小得看不见。
UE的项目设置默认是1 Unreal Unit = 1厘米,因此一个两米高的角色资产在UE里的实际数值是200。Unity的默认约定是1 Unity Unit = 1米,所以同样一个模型,如果直接把原始数值200塞进Unity,导入结果会是200米高。有些FBX工具通过文件头里的UnitScaleFactor来标记单位,Unity读取到厘米标记后会套用0.01的Scale Factor。如果你的插件或DCC工具没有正确写入单位标记,Unity就无法自动换算,此时就必须在Model Importer的手动Scale Factor里填0.01。
这个坑我建议彻底交给插件处理:在导出时主动把顶点数据缩放0.01倍,让FBX里存储的数值就符合"米"的语义。这样Unity侧不管读不读单位标记,结果都是正确尺寸。
4.3 法线贴图与粗糙度的处理
材质Header里最容易被忽略两项:一是粗糙度与光滑度的关系,二是法线贴图绿色通道的翻转。这两项搞错,材质表面看起来就不对,但又不容易一眼看出是哪里的问题。
UE的PBR工作流以Roughness为输入,值越大表面越粗糙,值为0是镜面。Unity的Standard着色器用Smoothness表示光滑程度,值为1是镜面。两者恰好是互补关系:Smoothness = 1 - Roughness。所以导出时不能简单地把UE粗糙度贴图原样塞进Unity的Smoothness通道,必须做灰度反转(或者说用反相输出)。插件如果自动处理了,你在Unity里看到的Smoothness贴图,颜色会整体偏亮(因为UE粗糙度贴图通常偏灰度偏低,反相后更接近白色)。
法线贴图也有一处天生冲突。通俗地说,两款引擎对法线贴图"凹陷方向"的解释是不同的,直接复用同一个法线贴图,会让凸起变成凹陷,浮雕看起来像凿痕。Unity的解决方案是在纹理导入面板提供Flip Green Channel选项,也就是翻转法线贴图的Y通道。很多流程里大家不知道这个选项的存在,看到导入后的模型表面全反了就以为是模型坏了。
所以这块的经验是:拿到底材质贴图,先确认两个事情——粗糙度贴图在进入Unity后是否变成了Smoothness(以及是否反转),法线贴图是否勾选了Flip Green Channel。这两项对了,材质至少能看。
4.4 这些逻辑如何被封装成插件选项
这部分说说插件设计逻辑,有助于理解为什么导出面板是那样布局。
在管线工具的设计里,把需要用户操心的事情全部收拢到几个复选框里,比让用户自己去调Unity导入设置要可靠得多。这也让我意识到,做工具做得好不好,关键在于能否把隐性知识显性化。比如坐标轴转换,在传统流程里你需要记住"UE到Unity绕X轴转-90度",但插件把它变成了Convert Coordinate复选框;单位换算需要记住"0.01倍缩放",插件把它变成了Convert Unit复选框。这些选项要么不勾,要么勾上,不会再出现"导一次试一次,错了再换一种设置试"的痛苦循环。
我还注意到,插件对"命名约定"的依赖比之前想象的更强。因为Unity的自动材质管线其实是通过贴图后缀来识别贴图用途的,所以统一命名约定是整个流程能自动化的基石。反过来,如果你在UE里贴图命名不规范,插件自动处理后也会出现无法识别的贴图,最终材质会缺少某些通道。这也是为什么我前面反复强调,在使用这类插件之前,先把UE资产命名整理成规范。
5. 实测最容易翻车的三个环节和排查思路
5.1 尺寸缩放翻车现形记
我自己的第一个教训就是尺寸。当时测试导出一个UE里尺寸为500厘米的箱子,导入Unity后变成了500单位,在Unity里默认单位是米,也就是说一个5米的东西变成了500米。当时的渲染场景里模型直接穿透天空盒。
排查链路很简单,但容易被忽略:先看Unity Model Importer里的Scale Factor,如果是0.01且模型大小正常,说明单位标记正确;如果Scale Factor是1但模型大得离谱,说明导出时没有进行单位转换或FBX里没有写入厘米标记。另一个检查方式是看场景里物体的Transform Scale是否变成了奇怪的数值。如果插件导出时做了缩放,一般Scale是1;如果靠Unity导入缩放,则Scale Factor会非1。两种情况都能用,但最好保证整个项目的所有资产采用同一种方式,避免有的模型靠导入缩放、有的模型靠顶点缩放,最后尺寸标准不一致。
5.2 材质变紫或全是黑的排查顺序
材质出问题是最常见的,因为涉及的因素最多。我总结了一套排查顺序,可以帮你快速定位。
先看导入后的材质球是否呈现默认的洋红色/紫色,这代表Shader丢失或不可用。此时优先检查Shader是否与渲染管线匹配:URP/HDRP项目用Standard Shader就会出现紫色,需要替换为Lit Shader。
如果材质不是紫色但看起来全黑或过暗,先检查贴图的颜色空间,重点看Metallic、Smoothness、Normal是否被误标为sRGB。然后看法线贴图是否勾了Flip Green Channel,没勾的话表面光照方向反了也会很奇怪。最后看Smoothness的纹理是否映射正确,很多情况是因为Roughness没有被反相,导致原本粗糙的表面变得高光全白或油腻。
5.3 动画和骨骼错乱时怎么判断
动画导入Unity后常见的现象有几种:模型呈T-Pose但动画不播放;播放了但模型扭曲成一团;动了但是方向不对。
遇到骨骼扭曲的,十有八九是骨骼命名或骨骼层级在导出时发生了错配。第一步检查Unity里模型的Rig类型:如果你选择了Humanoid,而骨骼命名和标准Humanoid映射差别很大,骨骼重定向会失败。此时改Generic导入通常能解决,但会失去人形重定向的能力。
如果动画播放后整体位置不对,检查FBX导入选项里的Animation选项卡,看Bake Axis Conversion和Resample Curves选项。对于UE导出Root Motion动画,建议开启Root Transform的Bake Into Pose选项,避免动画中角色位置变化在Unity里重复叠加。这里说一个经验:UE里做的动画进入Unity后,有时会感觉节奏比原版慢或快,多半是FBX导入时的采样率问题,勾选Resample Curves并设置合适帧率即可。
5.4 建立自己的导入验收清单
经历了几次"表面导入成功、实际全错"之后,我给自己定了一套验收清单。每次批量导入后,按顺序检查一遍:
- 模型尺寸是否符合预期(用Unity里的立方体对比,或者按场景单位手填一个已知尺寸检查)。
- 模型朝向是否正确(前方面朝向是否和Unity的蓝色Z轴正向对应)。
- 材质是否包含全部PBR通道,重点看Smoothness和Normal Map。
- 法线贴图是否勾选Flip Green Channel。
- 碰撞体是否生成,Mesh Collider是否引用的是碰撞网格。
- 动画是否正常播放,骨骼是否有扭曲或位移。
这套清单看起来简单,但真实项目中90%的"插件不好用"其实是这些基础项没过关。工具做对了98%,剩下的2%要靠使用者的检查习惯兜底。
6. 落地后的二次加工与优化建议
6.1 进入Unity后的资产整理习惯
插件把资产搬进来只是第一步,真正决定管线效率的是你进来之后怎么整理。我个人的经验是,在Unity资产目录里按功能区而非按来源区分目录:Models、Materials、Textures、Animations、Prefabs。UE里的原始目录结构可以作为参考,但Unity侧一定要按Unity团队的协作习惯组织,否则之后Unity程序员会抱怨找不到资源。
材质重命名也值得一提。插件生成的材质名可能直接沿用UE的资产名,比如M_Chest_Inst,但Unity里大家都习惯用MAT_Chest或Chest_Material。统一命名规范这件事,越早做越省钱,拖到几十个材质后再改就会牵扯无数Prefab引用。
6.2 LOD、碰撞体与预制体组装
如果UE侧已经有LOD组,导入Unity后不会自动生成LOD Group,需要你在Unity里手动创建。通常操作是选中主模型,在LOD Group组件里依次拖入LOD0到LOD2的子模型。如果插件导出的LOD是按文件名后缀区分的,可以写个简单Editor脚本来批量创建LOD Group,避免一个个拖。
碰撞体方面,UCX_前缀的碰撞网格可以直接生成Mesh Collider,但要提醒一句:Mesh Collider在移动物体时性能开销高,静态场景用没问题,动态交互物件建议手动改成Box/Sphere/Capsule组合。工具能帮你省掉从零搭建Collider的时间,但物理体选择仍然需要根据玩法做决策。
最后要做一个整体Prefab:把模型、碰撞体、材质、动画控制器组装成一个Prefab,后续场景里全部用它来放置。这一步是我踩过坑后养成的习惯——如果直接拖模型骨架进场景,多个场景实例会共享同一个模型资源,改一个跟着全改,而且场景里会出现大量层次混乱的裸节点。Prefab化后,场景整洁度和迭代效率都会好很多。
6.3 什么时候不该用这个插件
工具好用不代表要无脑用。以我自己的经验,这几种情况你最好冷静评估一下。
第一,如果你只需要从UE里拿一个简单的静态网格,手动导出FBX再导入Unity,一分钟就能搞定,没必要整套管道。第二,如果UE侧资产本身就使用了大量Shader特殊性或自定义材质函数,插件生成的PBR属性映射可能不理想,这时候建议只导Mesh,材质到Unity里重做。第三,如果目标是运行时动态加载而不是编辑器内编辑,那走AssetBundle或Addressables的方式会更合适,这种插件导出的工程资产只能作为开发期的数据源。
另外我也要提醒一句,跨引擎资产迁移有一个无法绕过的本质问题:引擎特性永远无法100%等价。插件能做的是把资产数据无损地带过去,但光照质量、特效表现、物理材质这些"运行体验"层面的东西,始终要结合目标引擎重新调优。把期望设为"导入即还原",大概率会失望;但设成"导入即达到可调整的90%",这个插件就非常值了。
我在实际项目中,用这套流程完成了一个包含四百多个资产的关卡迁移,从UE原型到Unity可用状态大约用了两个工作日,其中大部分时间花在光照重烘焙和特效重建上,资产本身的导入几乎没有出过大的纰漏。对于经常需要在两个引擎之间切换的团队来说,值得认真考虑。