Unity3d:在 Unity 4 中管理资源依赖关系

推荐:将NSDT场景编辑器加入你的3D工具链
3D工具集:NSDT简石数字孪生

在 Unity 4 中管理资源依赖关系

在 Unity 5 之前的 Unity 版本中,必须使用编辑器定义资源依赖关系脚本
独自。(在Unity 5中,我们在编辑器中提供了工具,用于将资源分配给特定的捆绑包,并且依赖项处理是自动的)。此信息是为在 Unity 4 中处理旧项目的人员提供的,假设您使用的是 Unity 4。

捆绑包中的任何给定资产都可能依赖于其他资产。例如,模型可以包含材料,而这些材料又利用纹理和着色
.可以将资产的所有依赖项及其包含在捆绑包中。但是,来自不同捆绑包的多个资源可能都依赖于一组共同的其他资源(例如,几种不同的建筑物模型可能使用相同的砖块纹理)。如果共享依赖项的单独副本包含在具有使用该依赖对象的每个捆绑包中,则在加载捆绑包时将创建资产的冗余实例。这将导致内存浪费。

为了避免这种浪费,可以将共享依赖项分离到一个单独的捆绑包中,并简单地从任何包含需要它们的资产的捆绑包中引用它们。首先,需要通过调用 BuildPipeline.PushAssetDependencies 来启用引用功能。然后,需要构建包含引用依赖项的捆绑包。接下来,在构建引用第一个捆绑包中的资产的捆绑包之前,应再次调用 PushAssetDependencies。可以使用对 PushAssetDependencies 的进一步调用来引入其他级别的依赖关系。引用级别存储在堆栈上,因此可以使用相应的 BuildPipeline.PopAssetDependencies 函数返回级别。推送和弹出调用需要平衡,包括在构建之前发生的初始推送。

在运行时,您需要先加载包含依赖项的捆绑包,然后再加载引用它们的任何其他捆绑包。例如,您需要先加载共享纹理包,然后再加载引用这些纹理的单独材质包。

资产编号

如果您预计需要重新构建属于依赖关系链的资产包,则应在启用 BuildAssetBundleOptions.DeterministicAssetBundle 选项的情况下构建它们。这保证了每次重建捆绑包时,用于标识资产的内部 ID 值都是相同的。

使用此方法构建资产包时,将为其中的对象分配一个 32 位哈希代码,该代码使用资产包文件的名称、资产的 GUID 和资产中对象的本地 ID 进行计算。因此,请确保在重建时使用相同的文件名。另请注意,拥有大量对象可能会导致哈希碰撞
阻止 Unity 构建资源包。

着色器依赖项

每当着色器作为参数直接引用在 BuildPipeline.BuildAssetBundle 中,或者间接引用选项 BuildAssetBundleOptions.CollectDependencies,着色器的代码就会包含在资源包中。如果单独使用 BuildAssetBundle 创建多个资源包,这可能会导致问题,因为引用的着色器将包含在每个生成的捆绑包中。可能存在冲突,即当您混合不同版本的着色器时,因此您必须在修改着色器后重建所有捆绑包。着色器的代码也会增加捆绑包的大小。为了避免这些问题,您可以使用 BuildPipeline.PushAssetDependencies 将着色器分隔到单个捆绑包中,这将允许您仅更新着色器捆绑包。作为如何实现此工作流的示例,您可以创建一个预 置
这包括对所需着色器的引用:

C# 示例

using UnityEngine;

public class ShadersList : MonoBehaviour {
    public Shader[] list;
}


创建一个空对象,分配脚本,将着色器添加到列表中并创建预制件,即“着色器列表”。然后,您可以创建一个导出器来生成所有分发包并更新着色器捆绑包:

C# 示例

using UnityEngine;
using UnityEditor;

public class Exporter : MonoBehaviour {
    
    [MenuItem("Assets/Export all asset bundles")]
    static void Export() {
        BuildAssetBundleOptions options = 
            BuildAssetBundleOptions.CollectDependencies | 
            BuildAssetBundleOptions.CompleteAssets | 
            BuildAssetBundleOptions.DeterministicAssetBundle;
        
        BuildPipeline.PushAssetDependencies();
        BuildPipeline.BuildAssetBundle(AssetDatabase.LoadMainAssetAtPath("Assets/ShadersList.prefab"), null, "Data/ShadersList.unity3d", options);
            
        BuildPipeline.PushAssetDependencies();
        BuildPipeline.BuildAssetBundle(AssetDatabase.LoadMainAssetAtPath("Assets/Scene1.prefab"), null, "Data/Scene1.unity3d", options);
        BuildPipeline.BuildAssetBundle(AssetDatabase.LoadMainAssetAtPath("Assets/Scene2.prefab"), null, "Data/Scene2.unity3d", options);        
        
        BuildPipeline.PopAssetDependencies();
        BuildPipeline.PopAssetDependencies();
    }
    
    [MenuItem("Assets/Update shader bundle")]
    static void ExportShaders() {
        BuildAssetBundleOptions options = 
            BuildAssetBundleOptions.CollectDependencies | 
            BuildAssetBundleOptions.CompleteAssets | 
            BuildAssetBundleOptions.DeterministicAssetBundle;
        
        BuildPipeline.PushAssetDependencies();
        BuildPipeline.BuildAssetBundle(AssetDatabase.LoadMainAssetAtPath("Assets/ShadersList.prefab"), null, "Data/ShadersList.unity3d", options);
        
        BuildPipeline.PopAssetDependencies();
    }
}


请记住,必须先加载着色器包。此方法的一个缺点是,当对象量太大时,选项 BuildAssetBundleOptions.DeterministicAssetBundle 可能会由于冲突哈希而产生冲突。在这种情况下,生成将失败,并且无法单独更新着色器包。在这种情况下,您必须删除该选项并重新构建所有资源包。

3D建模学习工作室整理翻译,转载请标明出处!

上一篇:Unity3d:在 Unity 4 中创建资源包 (mvrlink.com)

下一篇:Unity3d:动画 (mvrlink.com)

NSDT场景编辑器 | NSDT 数字孪生 | GLTF在线编辑器 | 3D模型在线转换 | UnrealSynth虚幻合成数据生成器 | 3D模型自动纹理化工具
2023 power by nsdt©鄂ICP备2023000829号