UE5.8 资产导入管线:从手动拖拽到自动化流水线
美术外包把第一批场景模型传过来的那天,小林在 Content Browser 前面坐了一下午。压缩包里躺着两百多个 FBX,命名从 Box_01 到 Rock_Final_Final_03,材质球有的叫 lambert2,有的直接是 initialShadingGroup。他一个个拖进引擎,点 Import,改单位,勾 Smoothing Group,取消 Import Materials,再手动打开每个 Static Mesh 启用 Nanite、设置 LOD、加 Collision。晚饭凉透的时候,他才处理到第八十个。
那天晚上小林算了笔账:按这个速度,每周外包进来的模型至少需要两个人各抽出两天做导入和清理。更麻烦的是人手操作容易出错。上周一把武器的碰撞体漏设,策划在关卡里直接穿墙;再上周一张法线贴图被当成反照率导入,角色胸口像抹了一层油。这些问题不会出现在代码审查里,因为它们发生在导入阶段,而导入阶段往往被视为体力活。
UE5.8 的导入管线其实提供了很多把体力活自动化的机会。从拖拽导入时的 Import UI,到 Dataprep 的可视化导入图表,再到 Python 和 C++ 里的程序化导入接口,项目可以把规则沉淀成流程。本文从三个真实场景切入,把 UE5.8 资产导入管线拆成八个部分讲清楚。
1. FBX / glTF / USD 导入设置
三种主流格式在 UE5.8 里的导入路径各有侧重。FBX 是游戏行业用得最久的中间格式,几乎每家外包都提供。glTF 作为 Khronos 主推的开放格式,在 Web、移动端和工具链交换里越来越常见。USD 则是影视和大型团队协作的宠儿,Epic 在 UE5 里持续加大对它的投入。
FBX 导入时需要关注的核心选项集中在 FFbxImportUI 里。Mesh 页签下,Combine Meshes 决定多个 Mesh 是否合并成一个 Static Mesh;Build Nanite 让引擎在导入时直接构建 Nanite 数据;Generate Lightmap UVs 会基于现有 UV 通道再包一层光照贴图 UV。Animation 页签下,Import Animations 和 Animation Length 决定动画片段的截取方式。Material 页签下,Import Materials 和 Import Textures 可以控制是否同步创建材质和贴图。很多项目会关闭这两个选项,因为材质模板需要在引擎内按规范重建。
glTF 导入由 glTFRuntime 或官方 Khronos glTF Importer 处理。UE5.8 自带的 Khronos 插件支持 glTF 2.0 的核心规范,包括 PBR 材质、骨骼动画和 morph target。导入时可以选择是否把 glTF 的 metallic-roughness 工作流映射到 Unreal 的默认材质,也可以保留原始纹理引用。如果 glTF 里用了 MSFT_packing_occlusionRoughnessMetallic 之类的扩展,插件会尝试解析通道打包关系。
USD 导入和前两者的最大区别在于它不是文件导入,而是 Stage 引用。UE5.8 支持把 USD Stage 直接拖进关卡,也可以把某个 prim 转换为 Static Mesh 或 Skeletal Mesh 资产。USD 的 Variant Set、Payload、Layer 都可以在导入或引用时保留。大型项目通常不会让美术把 USD 直接 Cook 进包体,而是作为源文件存在,最终导出成 FBX 或经过 Dataprep 处理成 uasset。
flowchart TD
subgraph source ["外部源资产"]
fbx["FBX 文件"]
gltf["glTF 文件"]
usd["USD Stage"]
end
subgraph importer ["导入层"]
ui["Import UI"]
dataprep["Dataprep"]
python["Python Import Task"]
factory["Asset Factory"]
end
subgraph engine ["引擎资产"]
mesh["Static Mesh"]
tex["Texture"]
mat["Material"]
anim["Animation"]
end
fbx --> ui
fbx --> dataprep
gltf --> ui
usd --> dataprep
dataprep --> factory
python --> factory
ui --> factory
factory --> mesh
factory --> tex
factory --> mat
factory --> anim上图把三种源资产和三条导入路径放在一起。FBX 和 glTF 通常走 Import UI 或 Dataprep;USD 更多走 Dataprep 做批量转换,或者作为 Stage 直接引用。无论走哪条路,最终都落到引擎的 Asset Factory 上生成 uasset。
2. Import UI 与选项
Import UI 是美术和策划最熟悉的导入入口。把文件拖到 Content Browser,引擎会弹出导入对话框。对话框里的选项很多,但真正需要每次调整的其实不多。UE5.8 允许把当前选项保存为 Import Preset,下次导入同类型文件时直接套用。
Mesh 页签下的关键选项包括:
- Vertex Color Import Option:是否导入顶点色,以及如何处理覆盖。
- Build Nanite:是否在导入时构建 Nanite,取决于项目对高密度网格的策略。
- Build Scale3D:缩放因子,常用于修正 DCC 工具和引擎之间的单位差异。
- Generate Lightmap UVs:自动生成光照贴图 UV 通道。
- Transform Vertex to Absolute:是否把顶点变换烘焙到世界空间。
Material 页签下,大部分项目会关闭 Import Materials 和 Import Textures。引擎根据 FBX 材质名生成的默认材质往往不符合项目规范,后续还是要替换。不如在导入前就让外包按命名规范提供纹理,导入后用材质实例模板批量指定。
Animation 页签需要留意 Animation Length 的三个选项:Exported Time、Animated Time 和 Set Range。导出的时间轴范围如果不一致,会导致动画片段长短不一,影响蒙太奇拼接。Skeleton 字段必须指向项目内已有的 Skeleton 资产,否则引擎会为每个文件新建一个 Skeleton,造成骨骼资产爆炸。
Misc 页签里有 File Path、Override Full Name、Enable Preserve Local Transform 等高级选项。批量导入时,Preserve Local Transform 如果为 false,多个子物体的相对位置会被重置,场景道具导入后可能全部堆在原点。
flowchart TD
A["拖拽 FBX 到 Content Browser"] --> B{是否显示 Import UI}
B -->|"是"| C["配置 Mesh/Material/Animation 选项"]
B -->|"否"| D["使用上次预设"]
C --> E["保存为 Import Preset"]
D --> F["生成 uasset"]
E --> F
F --> G["检查 Nanite/LOD/Collision"]小林后来把常用配置保存成两份 Preset:一份给场景静态道具,勾选 Build Nanite、Generate Lightmap UVs、不导入材质;一份给角色装备,关闭 Nanite、导入 Morph Target、指定项目 Skeleton。每次导入时直接选 Preset,出错率明显下降。
3. Dataprep 自动化导入
Import UI 适合单次或小批量导入。当外包一次性丢过来几百个文件时,Dataprep 才是正解。Dataprep 是 UE5 里的一套可视化数据准备工具,核心思想是把导入流程拆成抓取、过滤、转换、输出四个阶段。
小林用 Dataprep 做了一个自动导入图表。图表开头是一个 File Source 节点,指向外包文件共享目录。接下来是一个 Filter 节点,按文件名前缀把静态道具和角色装备分开。再后面跟一个 Transform 节点,给所有 SM_ 开头的 Static Mesh 启用 Nanite、设置 LOD Group 为 SmallProp、生成 Simple Collision。最后把所有结果输出到 /Game/Imported/<日期> 目录,方便版本控制提交。
Dataprep 的好处是规则可视化,美术自己也能看懂。老王帮小林把图表整理好后,直接交给外包负责人一份操作说明:把文件放到共享目录,打开 Dataprep 资产点执行,十分钟后去 Content Browser 检查。原先两个人两天的活,现在一个人半天就能跑完,剩下的时间只做抽样检查。
sequenceDiagram
participant TD as "技术美术"
participant DP as "Dataprep Asset"
participant FT as "文件源"
participant IF as "Import Factory"
participant CB as "Content Browser"
TD->>DP: 创建导入图表
DP->>FT: 抓取文件夹内 FBX
FT-->>DP: 返回文件列表
DP->>IF: 批量执行导入
IF-->>DP: 返回 Static Mesh
DP->>DP: 过滤名称、设置 LOD、生成 Collision
DP->>CB: 输出到 /Game/Imported
CB-->>TD: 显示导入结果Dataprep 也支持 Python 扩展。如果内置节点满足不了需求,可以写自定义 Python Operator 插入到图表里。比如按文件大小过滤掉空模型、按命名自动分组贴图、或者调用外部命令行工具做预处理。自定义 Operator 的输入是一张 Dataprep Context 表,输出是修改后的 Context,和 Houdini 里的节点思路类似。
4. 自动化导入规则
除了 Dataprep,UE5.8 还提供多条程序化导入路径。最常见的是 unreal.AssetImportTask,它可以在 Python 里构造一次完整的导入任务,不弹 Import UI,直接把文件转成 uasset。
下面这段脚本是小林给角色装备批量导入写的。它关闭材质和贴图导入,指定项目 Skeleton,启用 Combine Meshes,导入后立刻保存。
import unreal
task = unreal.AssetImportTask()
task.filename = r"D:\\Assets\\Characters\\SK_Hero_Armor_01.fbx"
task.destination_path = "/Game/Characters/Armors"
task.destination_name = "SK_Hero_Armor_01"
task.automated = True
task.save = True
factory = unreal.FbxFactory()
factory.import_ui.b_import_materials = False
factory.import_ui.b_import_textures = False
factory.import_ui.b_import_animations = False
factory.import_ui.b_import_mesh = True
factory.import_ui.skeletal_mesh_import_data.b_import_morph_targets = True
factory.import_ui.skeletal_mesh_import_data.set_editor_property("mesh_type_to_import", unreal.FBXImportType.FBXIT_SKELETAL_MESH)
asset_tools = unreal.AssetToolsHelpers.get_asset_tools()
asset_tools.import_asset_tasks([task])脚本里 automated = True 是关键。它告诉引擎不要弹出 Import UI,完全按代码里的配置执行。save = True 让导入的资产立刻写盘,避免脚本退出后丢失。mesh_type_to_import 必须显式指定,否则混合包含 Mesh 和 Animation 的 FBX 可能被误判。
如果要批量导入整个目录,可以外层套一个 os.walk 循环,按文件前缀决定目标路径和导入选项。小林把这个脚本挂到 Editor Utility Widget 的按钮上,美术选中文件夹后点一下就能跑。
C++ 层面也有对应的 UAssetToolsSubsystem::ImportAssetTasks 接口。它适合需要集成到自定义编辑器插件或命令行 Cook 流程的场景。比如构建机每晚从版本控制拉取最新源美术文件,调用导入接口生成 uasset,再触发 Cook 和测试。
5. LOD 与 Collision 自动设置
导入静态网格体时,LOD 和 Collision 是最耗人工的两个环节。UE5.8 支持多种自动处理方式,项目只需一次性定好规则。
LOD 的来源可以有两种:DCC 里预先做好,或者引擎自动生成。预先做好的 LOD 需要在 FBX 里按命名规范设置,例如 SM_Rock_01、SM_Rock_01_LOD1、SM_Rock_01_LOD2。导入时引擎会把同名 Mesh 识别为 LOD 链。引擎自动生成的 LOD 则在 Static Mesh Editor 里通过 Simplification 设置控制,按屏幕像素阈值或距离切换。
Collision 也有两条路。第一条是在 DCC 里做简化的碰撞体,命名以 UCX_ 或 UBX_ 等前缀开头,FBX 导入时自动识别。第二条是在引擎里用 Collision 菜单自动生成 Box、Sphere、Capsule 或复杂凸包。Dataprep 和 Python 都可以调用 CreateBodySetup 和 AddCollision 接口批量设置。
Nanite 的自动启用规则需要根据项目经验定一个阈值。小林团队的规定是:三角面数超过两千的静态网格体默认开启 Nanite;低于两千的保持传统 Static Mesh,避免 Nanite 带来的少量开销。这个规则可以写成 Dataprep 条件节点,也可以写进 Python 脚本。
T_{nanite} = \begin{cases} \text{启用 Nanite}, & N_{tri} > 2000 \\ \text{传统 Static Mesh}, & N_{tri} \le 2000 \end{cases}公式里 表示导入后 Static Mesh 的三角面数。阈值 不是固定值,场景复杂、远景物体多的项目可以适当调高,室内近距离道具则可以调低。规则定好后,重点是不让美术每次手动判断。
graph LR
A["FBX 含 LOD 命名"] --> B["LOD Group 设置"]
C["无 LOD 单网格"] --> D["引擎内生成 LOD"]
E["UCX_ 前缀碰撞体"] --> F["自动识别为 Collision"]
G["三角面数 > 阈值"] --> H["启用 Nanite"]
B --> I["输出 Static Mesh"]
D --> I
F --> I
H --> I上图把四条自动规则汇总。项目实际运行时,这些规则通常并行执行:导入一个 FBX 时,同时检查 LOD 命名、扫描碰撞体前缀、读取三角面数,最终输出一个配置完整的 Static Mesh。
6. 纹理导入与压缩
纹理导入看似简单,但参数一旦设错,后期性能会吃大亏。UE5.8 的 Texture Import Settings 里,Compression Settings 和 Texture Group 是最核心的两个字段。
Compression Settings 决定纹理用哪种块压缩格式。常见选择包括:
- Default (BC1/BC3):普通 RGB 或 RGBA 贴图,显存占用低。
- Normalmap (BC5):法线贴图,保留 XY 通道精度。
- Masks (BC4):单通道灰度贴图,如粗糙度、金属度、AO 的独立通道。
- UserInterface2D (BC7):UI 贴图,支持 Alpha 且质量高。
- HDR (RGB):高动态范围贴图,如光照贴图、天空盒。
Texture Group 则影响 Mipmap 生成、流送优先级和压缩质量。角色贴图通常选 Character,世界场景贴图选 World,UI 贴图选 UI。分组错了会导致纹理流送池分配不合理,低端机上出现模糊贴图。
纹理在显存里的占用可以用下面公式估算:
和 是纹理宽高; 是通道数; 是每通道字节数; 是块压缩比率。以一张 的 BC7 贴图为例,原始未压缩大小约为 ,BC7 按 或 压缩后显存占用降到 到 之间。加上 Mipmap 链,总占用再乘以约 倍。
小林团队定了一套命名规范:T_<Name>_D 表示反照率,T_<Name>_N 表示法线,T_<Name>_ORM 表示 Occlusion/Roughness/Metallic 合并贴图,T_<Name>_E 表示自发光。导入脚本根据后缀自动设置 Compression Settings 和 sRGB 开关。反照率要开 sRGB,法线和 ORM 必须关 sRGB,否则 PBR 光照会出错。
7. 导入管线与版本控制
资产导入管线和版本控制的关系经常被低估。项目里有两类文件:源美术文件和生成的引擎资产文件。源文件包括 .fbx、.obj、.gltf、.usd、.png、.tga 等,生成文件主要是 .uasset 和 .umap。
推荐的做法是:源文件纳入版本控制,生成的 uasset 也纳入版本控制。这听起来和代码构建不一样,但原因是引擎资产文件里包含很多导入设置、LOD、Collision、材质引用关系,这些内容如果让每个人本地重新导入,容易产生不一致。团队里最好只有一台构建机或一个指定人员负责执行导入脚本,其他人同步 uasset。
Perforce 是虚幻项目最常见的版本控制方案。二进制资产文件用 Perforce 的 Lock 机制避免同时修改。源文件和 uasset 放在不同目录,比如 /SourceArt/ 和 /Content/,权限分开。外包只上传源文件,内部美术只修改 Content 下的 uasset。
使用 Git 的项目需要注意 Git LFS 配置。uasset 文件通常较大,直接放进 Git 仓库会让仓库快速膨胀。LFS 把大文件指针存在仓库,实际内容放到 LFS 服务器。.gitattributes 里要加上 *.uasset filter=lfs diff=lfs merge=lfs -text 和 *.umap filter=lfs diff=lfs merge=lfs -text。
重新导入(Reimport)操作会读取源文件路径。如果文件被移动或重命名,Reimport 会失败。导入时最好在 Source File Path 里用相对路径或项目内统一路径,避免个人电脑的绝对路径写进 uasset。UE5.8 的 Import Settings 里可以指定 Source File Path 为项目相对路径,这样换台机器也能正常 Reimport。
8. 常见导入问题
即便有了自动化规则,导入阶段还是会遇到各种问题。下面列几个小林团队踩过的高频坑。
单位缩放错误。Maya 默认厘米,Blender 默认米,Max 默认英寸,UE 默认厘米。同一个模型在不同 DCC 里导出后尺寸可能差十倍。最稳妥的方法是在项目里约定统一单位,导入时通过 Build Scale3D 修正,并在 DCC 模板里设置好导出单位。
材质丢失或变成默认灰色。多半是因为 FBX 里的材质名和引擎里的材质名对不上,或者 Import Materials 被关闭后没有手动指定。建议导入时关闭自动创建材质,导入后在 Dataprep 或 Python 脚本里按命名规则批量替换材质实例。
骨骼朝向错乱。角色动画导入后手脚扭成麻花,通常是 Skeleton 选择错误或者 DCC 里的坐标轴没有按项目规范设置。项目应该规定 T-pose 和 bone up 轴,导入时固定指定项目 Skeleton,禁止让引擎自动生成新 Skeleton。
Nanite 模型没有碰撞或碰撞位置偏移。Nanite 网格本身不能直接作为碰撞体,必须额外设置 Collision Mesh。如果碰撞体在 DCC 里和渲染网格不在同一坐标系,导入后会出现偏移。解决方法是确保碰撞体和渲染体共享同一根节点,或者导入后在引擎里调整 Collision 偏移。
法线贴图显示错误。贴图导入后模型表面出现黑斑或条纹,常见原因有两个:法线贴图被错误地勾选了 sRGB,或者蓝通道方向与引擎默认不一致。UE 默认 DirectX 法线方向,如果源文件是 OpenGL 方向,需要在材质里翻转绿通道,或者导入时设置 Flip Green Channel。
USD Stage 加载极慢。USD 文件如果包含大量 prim 且没有启用 Payload,打开 Stage 时会把所有数据一次性加载进内存。解决方法是让美术在导出 USD 时把高密度几何体放到 Payload 里,按需加载。也可以先在 USD 工具里做 collapsed 或 combined prim,减少 prim 数量。
写在最后
资产导入管线不是项目初期的 glamour 工作,但它决定了后续内容生产能否跑起来。小林那批两百个 FBX 的事件之后,团队花了一周时间把导入规则写成 Dataprep 图表和 Python 脚本,又花两天把命名规范和版本控制流程定死。第一个月效果还不明显,三个月后内容更新节奏明显变快,美术花在重复导入上的时间少了近一半,导入相关的 Bug 单下降了七成。
好的导入管线有几个共同点:规则明确、流程可重复、错误可追踪。把人工判断转成代码判断,把个人经验转成团队规范,项目才能在中后期保持健康的资产结构。UE5.8 提供的工具已经够用了,关键是用起来。建立这套管线的过程本身也是一次团队沟通:程序、美术、策划坐下来把每一步规则对齐,才能避免后续反复返工。