Unity高性能glTF模型加载指南:glTFast核心原理与工程实践
1. 项目概述为什么glTFast是Unity开发者的新宠如果你正在Unity里折腾3D模型尤其是从各种建模软件比如Blender、Maya或者网上下载的模型资源那你一定对模型导入这个环节又爱又恨。爱的是精美的模型能让你的游戏或应用瞬间提升几个档次恨的是这个过程常常伴随着漫长的等待、诡异的材质丢失、巨大的内存占用甚至直接卡死编辑器。我经历过太多次导入一个几百兆的FBX文件Unity转圈圈转了五分钟然后告诉我“导入失败”。直到我遇到了glTFast这个痛点才被真正解决。glTF全称GL Transmission Format你可以把它理解为“3D界的JPEG”。它是由Khronos Group就是制定OpenGL、Vulkan标准的那个组织推动的开放标准目标就是成为网络上传输和加载3D模型的通用格式。相比于传统的FBX、OBJglTF是“为运行时而生”的。它天生就为Web和实时渲染优化文件结构更紧凑加载速度更快并且原生支持PBR基于物理的渲染材质、动画、骨骼等现代图形特性。而glTFast就是Unity官方钦点的高性能glTF加载库。它不是Unity内置的但却是Unity官方在GitHub上维护和推荐的项目地位特殊。它的核心就一个字快。通过高度优化的C#/Unity Job System/Burst编译器技术它能实现远超传统导入方式的加载速度并且支持运行时动态加载这对需要动态下载模型的应用如数字孪生、AR展示、大型开放世界游戏来说是革命性的。所以这个“完全指南”要解决的就是如何把glTFast这个利器无缝集成到你的Unity工作流中从环境配置、基础导入导出到高级功能优化和疑难杂症排查让你彻底告别模型导入的等待与焦虑。无论你是独立开发者、TA技术美术还是项目负责人掌握glTFast都意味着更高效的生产力和更流畅的用户体验。2. 核心思路与工作流设计在深入代码之前我们必须先理清思路传统工作流和基于glTFast的工作流到底有什么不同这决定了我们该如何重新设计资产管道。2.1 传统Unity模型工作流的瓶颈传统的流程通常是这样的美术人员在Blender/Max/Maya中完成模型制作导出为FBX或OBJ文件然后由程序或TA手动拖入Unity项目的Assets文件夹。Unity的Asset Pipeline会启动在后台进行一系列处理计算光照贴图UV如果没提前做好、生成网格碰撞体、压缩纹理、为模型创建Prefab和材质球等。这个过程我们称之为“编辑时导入”。它的主要问题在于阻塞式操作导入大型或复杂模型时Unity编辑器会卡住无法进行其他工作。资源膨胀FBX等格式为了兼容性包含大量冗余数据。Unity导入后还会生成对应的.meta文件和库文件导致项目资产文件夹体积庞大。灵活性差模型一旦导入其缩放、材质球生成规则就被固定。如果想在运行时根据设备性能动态切换不同LOD细节层次的模型文件或者动态下载更新模型传统方式非常笨重。平台依赖某些FBX的特性可能在不同版本的Unity或不同建模软件之间表现不一致导致材质丢失、动画错乱等“玄学”问题。2.2 基于glTFast的现代工作流glTFast引入了一种“运行时加载”的范式。你的glTF模型文件.gltf/.glb不再必须放在Assets文件夹下。它们可以放在StreamingAssets随包发布、PersistentDataPath设备可写目录甚至是从远程服务器直接下载的字节流。新工作流的优势非阻塞异步加载加载过程在后台线程进行不会冻结主线程游戏或应用可以保持流畅响应并显示加载进度。资源精简glTF文件本身更小。由于是运行时解析不会在Library文件夹生成庞大的中间数据项目结构更清爽。动态化与热更新模型可以作为数据资源进行管理轻松实现动态下载、替换和更新无需重新打包App。标准统一glTF是开放标准避免了专有格式的兼容性问题。从Blender导出的glTF和在线的模型库如Sketchfab下载的glTF行为基本一致。设计决策点在你的项目中你需要决定哪些模型使用传统编辑时导入FBX哪些使用运行时加载glTF。一个实用的混合策略是核心、静态场景资产如主角模型、主要建筑。这些模型使用频率高对加载速度要求极致且不太变化。可以在编辑时通过glTFast的“预转换”功能将其转换为Unity原生的GameObject预制体享受运行时零加载开销的好处。动态、可下载内容如用户自定义的Avatar、商城道具、大型场景中的次要物件。这些完美契合glTFast的运行时加载模式。需要复杂Unity特定功能如与NavMesh系统深度集成、使用复杂的Shader Graph材质且需要大量编辑时调整的模型。可能暂时仍需FBX但未来glTFast的支持也在不断完善。注意glTFast并非要完全取代FBX。FBX在动画重定向、特定DCC工具链集成上仍有优势。glTFast是为你提供了另一个更高效、更现代的选项尤其是在网络传输和运行时动态化场景下。3. 环境配置与项目初始化理论讲完我们开始动手。第一步是把glTFast集成到你的Unity项目中。3.1 安装glTFast官方推荐并通过Unity的Package Manager进行安装这是最安全、最便于管理版本的方式。在Unity编辑器中打开Window Package Manager。点击左上角的号选择Add package from git URL...。输入glTFast的Git仓库地址https://github.com/atteneder/glTFast.git。你也可以使用更稳定的版本标签例如https://github.com/atteneder/glTFast.git#v5.0.0请查阅GitHub发布页获取最新版本号。点击Add。Unity会开始下载和解析包。为什么不用Asset Store版本或直接拖DLL通过Package Manager安装可以轻松更新、查看文档并且依赖关系如Newtonsoft Json会被自动管理。直接复制代码或DLL容易导致版本冲突和后续更新困难。3.2 关键依赖项检查glTFast依赖于一些其他包来实现特定功能。安装后请确保以下包也已就位通常Package Manager会自动处理Newtonsoft Json用于解析JSON格式的.gltf文件。Unity 2020及以上版本通常已内置。Unity Mathematics和Burst用于高性能数学计算和并行作业。这是glTFast“快”的核心保障。确保Burst包已安装且处于启用状态Jobs Burst Enable Compilation。Unity Mesh API(可选)用于更高效的网格数据操作。安装完成后你会在项目的Packages目录下看到com.atteneder.gltfast。此时你的代码中已经可以使用GLTFast命名空间下的所有类了。3.3 基础场景搭建为了测试我们创建一个最简单的加载场景新建一个空场景。在Hierarchy中创建一个空GameObject命名为“GltfLoader”。为其添加一个脚本组件我们暂时命名为SimpleGltfLoader.cs。至此glTFast的环境就配置好了。接下来我们将进入最核心的加载环节。4. 核心加载功能全解析这是glTFast的精华所在。我们将从最简单的同步加载开始逐步深入到生产环境必备的异步加载、实例化管理和自定义材质。4.1 同步加载最简单直接的入门同步加载会阻塞主线程直到模型加载完成仅适用于极小的模型或快速原型测试不推荐用于正式项目。using UnityEngine; using GLTFast; public class SimpleGltfLoader : MonoBehaviour { public string gltfFilePath; // 例如: Assets/StreamingAssets/model.glb void Start() { LoadModelSync(); } void LoadModelSync() { var gltf new GltfImport(); // 同步加载并实例化 bool success gltf.Load(gltfFilePath).Result; if(success) { success gltf.InstantiateMainScene(transform); } if(!success) { Debug.LogError(Failed to load or instantiate GLTF model.); } } }关键点解析GltfImport是核心类负责加载和解析glTF数据。Load方法接受文件路径或byte[]数组、Uri返回一个Taskbool。这里用.Result强制同步等待是造成阻塞的原因。InstantiateMainScene将加载的模型实例化为场景中的GameObject并作为当前脚本所在GameObject的子物体。4.2 异步加载生产环境的标配99%的情况你都应该使用异步加载。它不会卡住游戏并且可以方便地实现加载进度提示。using System.Threading.Tasks; using UnityEngine; using UnityEngine.UI; using GLTFast; public class AsyncGltfLoader : MonoBehaviour { public string gltfUrl; // 可以是本地路径或网络URL public Slider progressSlider; // 可选的UI进度条 public Text progressText; async void Start() { await LoadModelAsync(); } async Task LoadModelAsync() { var gltf new GltfImport(); // 1. 创建加载设置可选但推荐 var settings new ImportSettings { GenerateMipMaps true, // 为纹理生成Mipmap AnisotropicFilterLevel 3, // 各向异性过滤等级 NodeNameMethod NameImportMethod.OriginalUnique // 节点命名方式 }; // 2. 异步加载并提供进度回调 var loadTask gltf.Load(gltfUrl, settings); while (!loadTask.IsCompleted) { // 更新UI进度 if (progressSlider ! null) { progressSlider.value gltf.LoadingProgress; } if (progressText ! null) { progressText.text $Loading... {gltf.LoadingProgress:P0}; } await Task.Yield(); // 等待一帧避免死循环 } // 3. 检查加载结果 bool success await loadTask; if (!success) { Debug.LogError(Loading glTF failed!); // 可以尝试获取具体错误信息 // var logs gltf.LogMessages; return; } // 4. 异步实例化 var instantiateTask gltf.InstantiateMainScene(transform); success await instantiateTask; if (!success) { Debug.LogError(Instantiating glTF failed!); } else { Debug.Log(GLTF model loaded and instantiated successfully!); } } }为什么这么设计async/await是C#处理异步的现代语法清晰易读。LoadingProgress属性提供了0-1的加载进度便于制作加载界面。ImportSettings让你能精细控制导入行为比如是否生成Mipmaps对性能影响很大这在移动端尤其重要。分离Load和Instantiate两步让你可以在加载完成后选择在合适的时机如进入特定区域时再实例化模型实现更精细的内存管理。4.3 实例化管理与材质定制直接实例化出来的模型其材质是glTFast根据glTF文件内的PBR信息自动生成的Standard Shader材质。但你可能需要自定义Shader或者批量修改材质属性。async Task LoadAndCustomizeModelAsync() { var gltf new GltfImport(); bool loaded await gltf.Load(gltfFilePath); if (!loaded) return; // 方案1在实例化后遍历修改 var instantiateTask gltf.InstantiateMainScene(transform); bool instantiated await instantiateTask; if (instantiated) { Renderer[] renderers GetComponentsInChildrenRenderer(); foreach (var renderer in renderers) { // 替换为你的自定义材质 // renderer.material myCustomMaterial; // 或者修改原有材质的某些属性 foreach (var mat in renderer.materials) { mat.SetFloat(_Metallic, 0.5f); mat.SetColor(_EmissionColor, Color.blue); } } } // 方案2使用自定义实例化器更高级 var customInstantiator new MyCustomInstantiator(transform); await gltf.InstantiateMainScene(customInstantiator); } // 自定义实例化器继承自glTFast提供的基类 public class MyCustomInstantiator : GameObjectInstantiator { public MyCustomInstantiator(Transform parent) : base(parent) { } // 重写材质创建方法 public override Material CreateMaterial(UnityEngine.Material source, GLTFast.Schema.Material gltfMaterial) { // 根据glTF材质信息返回你自己的材质 if (gltfMaterial.pbrMetallicRoughness?.baseColorTexture ! null) { return new Material(Shader.Find(MyCustom/PBRShader)); } else { return base.CreateMaterial(source, gltfMaterial); // 使用默认 } } }实操心得方案1事后修改简单直接适合小范围调整。方案2自定义实例化器功能强大可以在模型创建的“源头”就控制材质、GameObject的生成逻辑适合需要深度定制的大型项目。例如你可以根据glTF材质中的extras自定义字段来决定使用哪套Shader。5. 高级功能与性能优化当基础加载满足需求后为了应对更复杂的项目尤其是移动端或WebGL我们必须关注性能和高级特性。5.1 资源卸载与内存管理glTFast加载的模型其纹理、网格数据会占用内存。动态加载的模型必须能被正确卸载否则会导致内存泄漏。public class ManagedGltfLoader : MonoBehaviour { private GltfImport _gltfInstance; private GameObject _instantiatedModel; async Task LoadModel() { if (_gltfInstance ! null) return; // 防止重复加载 _gltfInstance new GltfImport(); await _gltfInstance.Load(modelUrl); var instantiator new GameObjectInstantiator(transform); await _gltfInstance.InstantiateMainScene(instantiator); _instantiatedModel transform.GetChild(transform.childCount - 1)?.gameObject; } void UnloadModel() { // 1. 销毁实例化的GameObject if (_instantiatedModel ! null) { Destroy(_instantiatedModel); _instantiatedModel null; } // 2. 释放GltfImport持有的资源纹理、网格等 if (_gltfInstance ! null) { _gltfInstance.Dispose(); _gltfInstance null; } // 3. 可选手动触发垃圾回收谨慎使用 // Resources.UnloadUnusedAssets(); // System.GC.Collect(); } void OnDestroy() { UnloadModel(); } }关键点Dispose()方法至关重要。它释放了GltfImport对象内部持有的所有Unity引擎对象Texture2D, Mesh等。仅仅销毁GameObject是不够的那些Asset还留在内存中。5.2 加载性能深度调优使用GLB格式而非GLTF分离资源.glb是二进制格式将所有数据JSON、纹理、缓冲打包进一个文件。单文件加载比.gltfJSON文件外加多个.bin和图像文件的网络请求快得多也更容易管理。纹理优化压缩格式确保glTF中的纹理使用了合适的压缩格式如KTX2/Basis Universal。glTFast支持这些格式它们能显著减少纹理内存和加载时间。你可以使用工具如glTF-Transform对glTF文件进行优化和纹理转码。Mipmaps在ImportSettings中开启GenerateMipMaps这对渲染性能特别是远处物体的渲染有巨大好处。分辨率对于非重要模型可以考虑在导出或后期处理时降低纹理分辨率。网格优化Draco压缩glTF支持Draco几何体压缩。如果模型使用了Draco压缩glTFast可以解码它这能极大减少网络传输的网格数据量。确保你的模型导出时启用了Draco压缩Blender等工具支持并且glTFast的Draco依赖已正确安装DracoUnity包。利用Addressables或AssetBundles对于需要打包发布的模型可以将glb文件打包进Addressables或AssetBundle。glTFast可以直接加载来自AsyncOperationHandle的字节流从而与Unity成熟的资产管理系统无缝集成。5.3 动画与相机场景加载glTF文件可以包含动画和预定义的相机。glTFast也能很好地支持。async Task LoadModelWithAnimation() { var gltf new GltfImport(); await gltf.Load(glbPath); // 实例化 var instantiator new GameObjectInstantiator(transform); await gltf.InstantiateMainScene(instantiator); // 获取动画片段 var animationClips gltf.GetAnimationClips(); if (animationClips ! null animationClips.Length 0) { var animator GetComponentInChildrenAnimator(); if (animator ! null) { var runtimeController animator.runtimeAnimatorController as UnityEditor.Animations.AnimatorController; // 将AnimationClip添加到Animator Controller中... // 注意运行时动态管理AnimationClip需要更复杂的逻辑通常建议在编辑时处理。 } else { // 简单播放使用Animation组件如果模型带Skinning var animation GetComponentInChildrenAnimation(); if (animation ! null) { animation.clip animationClips[0]; animation.Play(); } } } // 获取相机信息glTF中的相机是定义需要手动创建Unity Camera var cameras gltf.GetCameras(); // ... 根据camera数据创建Unity Camera GameObject }注意事项glTF的动画系统与Unity的MecanimAnimator系统并非直接对应。glTFast提取出的是AnimationClip你需要自己将其配置到角色的Animator Controller中。对于复杂的角色动画目前更成熟的流程可能还是FBX。但对于简单的机械动画、变形动画glTFast完全够用。6. 常见问题排查与实战技巧即使按照教程操作在实际项目中你还是会遇到各种坑。这里记录了我踩过的一些以及解决方法。6.1 模型加载失败一片粉红Missing Material现象模型加载出来了但全部或部分显示为亮粉色Unity默认的错误材质色。排查步骤检查控制台错误首先查看Unity Console看是否有明确的Shader编译错误或纹理加载错误。检查纹理路径如果你加载的是.gltf分离资源确保.bin缓冲数据文件和纹理图片如.png,.jpg与.gltf文件在相对路径上是正确的。glTF文件内记录的是相对路径。最简单的方法是将所有相关文件放在同一目录下。检查Shader兼容性glTFast默认使用Unity的Standard Shader或URP/HDRP的Lit Shader来创建PBR材质。确保你的项目渲染管线Built-in, URP, HDRP支持这些Shader。在URP项目中需要安装glTFast URP或HDRP扩展包以提供正确的Shader。检查纹理格式某些特殊的纹理格式如WEBP可能需要Unity额外的支持。尝试将纹理转换为PNG或JPEG格式。6.2 加载缓慢甚至卡死现象调用加载函数后游戏帧率骤降或完全无响应。排查步骤确认是同步还是异步首先检查代码你是否错误地使用了.Result或.Wait()进行了同步调用务必使用async/await。检查模型大小和复杂度一个包含数百万多边形和4K纹理的模型在任何平台上加载都会慢。使用建模软件或glTF优化工具如glTF-Transform对模型进行减面、压缩纹理、合并网格等优化。检查是否启用了Draco解码如果模型用Draco压缩但项目中没有正确导入DracoUnity包glTFast会回退到软件解码可能非常慢。确保DracoUnity包已安装。使用性能分析器打开Unity Profiler (Window Analysis Profiler)在加载时查看主线程和Job线程的占用。如果主线程阻塞说明有代码在同步等待。如果Job线程繁忙说明解码任务繁重考虑优化模型。6.3 在WebGL或移动端上崩溃现象在编辑器里运行正常发布到WebGL或Android/iOS后崩溃或模型不显示。排查步骤文件路径问题在WebGL或移动平台文件系统路径与编辑器不同。绝对不要使用Application.dataPath。对于随包发布的文件使用Application.streamingAssetsPath对于可读写目录使用Application.persistentDataPath。对于网络加载确保URL正确且服务器CORS设置允许跨域请求WebGL。内存不足移动端和WebGL内存限制严格。使用Profiler的内存模块检查加载前后的内存占用。确保纹理格式是压缩的如ASTC, ETC2并开启了Mipmaps。考虑实现模型的按需加载和卸载。Shader变体缺失在构建项目时Unity可能会剥离未使用的Shader变体。确保你项目中的所有PBR材质所使用的Shader变体都被正确包含在构建中。可以在Project Settings Graphics的Shader Stripping设置中调整或者确保场景中有一个使用该材质的对象。多线程限制WebGL不支持真正的多线程因此Unity Job System和Burst在WebGL上的加速效果有限。这是平台限制只能通过进一步优化模型数据来缓解。6.4 从其他格式如FBX, OBJ转换为glTF你可能有大量现存FBX资产。要利用glTFast需要转换它们。推荐工具链Blender最强大的免费选择。安装官方glTF导出插件2.80版本已内置。在Blender中导入FBX然后选择File Export glTF 2.0。在导出设置中务必勾选关键选项Export Format: 选择.glb单一文件以获得最佳加载性能。Compression: 勾选Draco进行网格压缩。Images: 选择Automatic或转换为Basis Universal格式需额外设置。glTF-Transform (命令行)这是一个Node.js工具非常适合批量处理和自动化。# 安装 npm install -g gltf-transform/cli # 基本转换 (FBX需先通过其他工具如FBX2glTF转换) gltf-transform cp input.fbx output.glb # 强大的优化命令压缩纹理、网格、合并材质等 gltf-transform optimize input.glb output.glb --texture-compress webp在线转换器如https://products.aspose.com/3d/zh/conversion/fbx-to-gltf/或AnyConv.com适合偶尔转换单个文件。转换后检查转换后务必在简单的glTF查看器如https://gltf-viewer.donmccurdy.com/或Unity中用glTFast测试一下确保材质、动画和网格结构正确无误。7. 编辑时预转换兼顾性能与工作流对于确定会频繁使用、且不需要动态更新的核心模型我们可以利用glTFast的“编辑时导入”功能将其转换为原生的Unity Prefab从而获得最佳的运行时性能零加载开销和便利的编辑时调整能力。7.1 使用Gltf Asset ImporterglTFast提供了一个GltfAsset组件它可以在编辑模式下就执行加载和实例化并将结果保存为Prefab。在Project视图中右键选择Import New Asset但这里我们直接拖拽.glb或.gltf文件到Assets文件夹。Unity会将其识别为一种自定义资源。但实际上glTFast并没有创建一个真正的“Asset”。更常见的做法是在场景中创建一个空GameObject。为其添加GltfAsset组件。在GltfAsset组件的Url字段中指定你的glTF文件可以是Assets/下的相对路径。勾选Load On Start如果希望在运行时自动加载。关键步骤在编辑模式下点击GltfAsset组件上的Instantiate按钮。glTFast会立即加载该文件并在该GameObject下创建出所有模型节点。现在你可以像编辑任何其他Unity对象一样调整这个模型的材质、挂载脚本等。最后将这个包含GltfAsset组件和已实例化模型的GameObject拖回Project视图创建一个Prefab。这样你就得到了一个完全由Unity原生GameObject和Component构成的Prefab。在运行时这个Prefab的实例化速度就和普通Prefab一样快因为不需要再解析glTF文件了。GltfAsset组件在运行时要么不加载如果你取消了Load On Start要么加载速度极快因为数据已预转换。7.2 编写自定义编辑器脚本进行批量预转换对于大量模型手动操作不现实。我们可以编写一个简单的Editor脚本来自动化这个过程。using UnityEditor; using UnityEngine; using System.IO; using GLTFast.Editor; // 注意这是Editor命名空间 public class GltfBatchPrefabCreator : EditorWindow { [MenuItem(Tools/glTFast/批量创建Prefab)] static void Init() { GetWindowGltfBatchPrefabCreator(glTF to Prefab); } public string sourceDirectory Assets/Models/GLTF; public string targetPrefabDirectory Assets/Prefabs/Converted; void OnGUI() { GUILayout.Label(批量转换设置, EditorStyles.boldLabel); sourceDirectory EditorGUILayout.TextField(GLTF源目录, sourceDirectory); targetPrefabDirectory EditorGUILayout.TextField(Prefab目标目录, targetPrefabDirectory); if (GUILayout.Button(开始转换)) { ConvertAllGltfInDirectory(); } } void ConvertAllGltfInDirectory() { if (!Directory.Exists(sourceDirectory)) { Debug.LogError($源目录不存在: {sourceDirectory}); return; } if (!Directory.Exists(targetPrefabDirectory)) { Directory.CreateDirectory(targetPrefabDirectory); } string[] gltfFiles Directory.GetFiles(sourceDirectory, *.gltf, SearchOption.AllDirectories); string[] glbFiles Directory.GetFiles(sourceDirectory, *.glb, SearchOption.AllDirectories); string[] allFiles new string[gltfFiles.Length glbFiles.Length]; gltfFiles.CopyTo(allFiles, 0); glbFiles.CopyTo(allFiles, gltfFiles.Length); foreach (var filePath in allFiles) { CreatePrefabFromGltf(filePath); } AssetDatabase.Refresh(); Debug.Log($转换完成共处理 {allFiles.Length} 个文件。); } void CreatePrefabFromGltf(string gltfPath) { // 1. 创建父级GameObject并添加GltfAsset GameObject rootGo new GameObject(Path.GetFileNameWithoutExtension(gltfPath)); var gltfAsset rootGo.AddComponentGltfAsset(); gltfAsset.url file:// Path.GetFullPath(gltfPath); // 使用绝对路径 // 2. 在编辑模式下同步加载并实例化这里简化实际需处理异步 // 注意GltfAsset.Instantiate() 可能在编辑模式下有同步调用的方式或需使用EditorUtility.DisplayProgressBar和轮询。 // 此处仅为思路生产代码需更健壮可能需调用内部方法或使用反射。 Debug.LogWarning(此示例仅展示流程编辑模式下同步Instantiate需要更复杂的实现。); // 更实用的做法可能是调用一个模拟加载的进程或者使用glTFast的GltfImporter在编辑器中直接导入。 // 3. 假设实例化完成保存为Prefab string relativePath gltfPath.Substring(gltfPath.IndexOf(Assets)); string prefabPath Path.Combine(targetPrefabDirectory, Path.GetFileNameWithoutExtension(relativePath) .prefab); PrefabUtility.SaveAsPrefabAsset(rootGo, prefabPath); // 4. 清理临时GameObject DestroyImmediate(rootGo); } }重要提示上面的批量转换脚本是一个概念演示。在编辑器中同步执行GltfAsset的加载和实例化需要更精细的处理因为其底层是异步的。一个更可靠的方法是深入研究glTFast的编辑器代码(GltfImporter)或者考虑在运行时进行首次加载并保存为Prefab适用于开发期资源构建管线。这个脚本旨在为你提供一个自动化思路的起点。通过编辑时预转换你巧妙地将glTF的“高效传输”优势与Unity原生Prefab的“高性能运行时”优势结合了起来为不同类型的资产选择了最合适的工作流。