【AssetBundle】AssetBundleVariant的使用

本文详细介绍了Unity中的AssetBundleVariant技术,用于制作和管理多档LOD资源,以适应不同性能的设备。通过设置AssetBundleName和VariantName,构建并加载不同的AssetBundle变体,实现代码动态加载资源,从而优化游戏性能。

目录

1.AssetBundleVariant介绍

2.如何制作AssetBundleVariant

2.1 准备3档LOD资源

2.2 设置ab名以及variant名

2.3 构建AssetBundle的变体

​ 3.使用代码加载各LOD档资源


1.AssetBundleVariant介绍

AssetBundleVariant是Unity的AB变体技术,常用于制作LOD资源,用于适配多档机型性能优化策略,是非常好用的一种资源分级技术,帮助项目对资源的分类编辑、管理、构建、发布提供了极大的便利性。

AssetBundleVariant的最终存在形式,还是AB,例如hight、default、low三种变体,构建后得到的是ab.high、ab.default、ab.low三个ab,把后缀作为变量传入加载即可实现多档机型的AB资源使用管理了。

2.如何制作AssetBundleVariant

制作AssetBundleVariant非常简单。下面以制作p1.png的三档资源为例。

2.1 准备3档LOD资源

对于一张贴图p1.png,如果制作3种变体资源,首先要保证产出3份命名相同的p1.png并且目录不同,目的是为了从ab中加载Asset的时候使用相同的资源名。

2.2 设置ab名以及variant名

在每张贴图的右下角Inspector处设置AssetBundleName和VariantName即可。

2.3 构建AssetBundle的变体

构建很简单,直接看代码:

[@MenuItem("Tools/BuildAB")]
public static void BuildAB()
{
    BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath, BuildAssetBundleOptions.UncompressedAssetBundle | BuildAssetBundleOptions.StrictMode, BuildTarget.StandaloneWindows);
    AssetDatabase.Refresh();
}

 构建结束后,得到3个ab,分别是3个Variant对应的ab。

3.使用代码加载各LOD档资源

加载也很简单,直接看代码:

using UnityEngine;
using UnityEngine.UI;

public class TestLoadABVariant : MonoBehaviour
{
    public Image image;

    AssetBundle ab;

    string abName = "ab_p1";

    private void OnGUI()
    {
        if (GUILayout.Button("Set_H"))
        {
            string variantName = "h";
            LoadAndSetSprite(variantName);
        }
        if (GUILayout.Button("Set_D"))
        {
            string variantName = "d";
            LoadAndSetSprite(variantName);
        }
        if (GUILayout.Button("Set_S"))
        {
            string variantName = "s";
            LoadAndSetSprite(variantName);
        }
    }

    private void LoadAndSetSprite(string variantName)
    {
        if (ab != null)
        {
            ab.Unload(true);
        }

        ab = AssetBundle.LoadFromFile($"{Application.streamingAssetsPath}/{abName}.{variantName}");

        Sprite s = ab.LoadAsset<Sprite>("p1");

        image.sprite = s;

        image.rectTransform.sizeDelta = new Vector2(s.texture.width, s.texture.height);
    }
}

4.使用代码构建AssetBundleVariant

需要注意,只要这个ABName使用了Variant,那么此AB的其他Variant就不能为""空字符串。

var assetBundleBuilds = new AssetBundleBuild[]
{
   new AssetBundleBuild
   {
      assetBundleName = "ab_p",
      assetBundleVariant = "H",
      assetNames = new string[] { "Assets/H/p.png" }
   },

   new AssetBundleBuild
   {
      assetBundleName = "ab_p",
      assetBundleVariant = "",   // <- Cause error
      assetNames = new string[] { "Assets/D/p.png" }
   }
};

BuildPipeline.BuildAssetBundles(outputPath, assetBundleBuilds, BuildAssetBundleOptions.None, BuildTarget.Android);

AssetBundleVariant的使用方法介绍,到此全部完成。

### 创建自定义AssetBundle打包工具 在Unity中创建自定义AssetBundle打包工具能够极大地提高资源管理和分发效率。通过编写脚本,可以实现自动化构建过程并优化项目结构。 #### 定义菜单项用于触发打包操作 首先,在编辑器环境下扩展`Editor`类来添加一个新的菜单命令,允许开发者轻松启动资产捆绑包的生成流程: ```csharp using UnityEngine; using UnityEditor; public class CustomAssetBundleBuilder : Editor { [MenuItem("Tools/Create Custom Asset Bundles")] static void BuildCustomAssetBundles(){ string outputDirectory = "Assets/Output/AssetBundles"; // 清理旧文件夹下的所有内容 System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(outputDirectory); foreach (var file in di.GetFiles()) file.Delete(); foreach (var dir in di.GetDirectories()) dir.Delete(true); // 构建新的AssetBundles BuildPipeline.BuildAssetBundles( outputDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows ); } } ``` 此代码片段展示了如何利用`BuildPipeline.BuildAssetBundles()`函数指定目标平台以及输出目录位置[^1]。 #### 设置特定于项目的配置选项 对于更复杂的场景,可能需要支持更多定制化需求,比如为不同类型的资源分配不同的标签或变体版本号。这可以通过遍历选定的对象集合,并为其应用相应的属性值完成: ```csharp foreach(Object obj in Selection.objects){ if(obj != null && !string.IsNullOrEmpty(assetBundleName)){ AssetImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(obj)); importer.assetBundleName = assetBundleName; importer.assetBundleVariant = variantName; } } ``` 上述逻辑适用于批量修改所选对象所属的AssetBundle名称及其变种名[^2]。 #### 实现高效的缓存机制与内存管理策略 考虑到性能因素,应当设计合理的加载和释放规则以减少不必要的IO访问次数。理想情况下,应用程序只需关注所需的具体资源实例,而无需直接接触底层的AssetBundle实体。为此,建议引入一层抽象层负责处理这些细节工作[^3]: ```csharp public class ResourceManager{ private Dictionary<string, Object> loadedResources = new Dictionary<string,Object>(); public T Load<T>(string resourceName) where T : Object{ if(!loadedResources.ContainsKey(resourceName)){ var bundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath,resourceName+".bundle")); loadedResources[resourceName] = bundle.LoadAsset<T>(resourceName); } return loadedResources[resourceName] as T; } public void Unload(string resourceName){ if(loadedResources.ContainsKey(resourceName)){ ((Object)loadedResources[resourceName]).Unload(false); loadedResources.Remove(resourceName); } } } ``` 这段示例实现了简单的资源加载器接口,它可以根据给定的名字查找已存在的副本;如果不存在,则尝试从未压缩过的磁盘镜像读取数据并将其加入到内部字典表里待用。当不再需要某份素材时还可以调用相应的方法安全地清理掉它们占用的空间[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值