AssetBundle注意事项

最近在做优化游戏内存的工作,当然也就涉及到最重要的资源的加载释放。特此记录一下踩过的坑以及一些注意事项。关于AssetBundle的概念网上已经有很多资料了,这里就不提了。

1.打AB包的时候,用何种方式压缩AB?

现目前主要用3种不同的方式来打ab包:lzma压缩, lz4压缩,不压缩,以下分别对3种打包策略进行试验。

试验打包对象为一张1024*1024的图集对象,用了ETC2进行压缩。


打包代码如下:


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
public class Tools : Editor {

    private static  List<AssetBundleBuild> maps = new List<AssetBundleBuild>();

    [MenuItem("MyMenu/Build Assetbundle")]
    static private void BuildAssetBundle()
    {
        maps.Clear();
        string dir = Application.dataPath + "/StreamingAssets";

        if (!Directory.Exists(dir))
        {
            Directory.CreateDirectory(dir);
        }

        string spriteSetDir = Application.dataPath + "/SpriteSet";
        string[] dirs = Directory.GetDirectories(spriteSetDir, "*", SearchOption.AllDirectories);
        for (int i = 0; i < dirs.Length; i++)
        {
            string name = dirs[i].Replace(spriteSetDir, string.Empty);
            name = "SpriteSet/" + name.ToLower() + ".unity3d";
            string path = "Assets" + dirs[i].Replace(Application.dataPath, "");
            AddBuildMap(name, "*.png", path);
        }

        BuildPipeline.BuildAssetBundles(dir, maps.ToArray(), BuildAssetBundleOptions.None, BuildTarget.Android);
    }

    static void AddBuildMap(string bundleName, string pattern, string path)
    {
        string[] files = Directory.GetFiles(path, pattern);
        if (files.Length == 0) return;

        for (int i = 0; i < files.Length; i++)
        {
            files[i] = files[i].Replace('\\', '/');
        }
        AssetBundleBuild build = new AssetBundleBuild();
        build.assetBundleName = bundleName;
        build.assetNames = files;
        maps.Add(build);
    }
}
加载ab测试代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Diagnostics;
public class Loader : MonoBehaviour {

	// Use this for initialization
	void Start () {
        System.Diagnostics.Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start(); //  开始监视代码运行时间

        //code
        AssetBundle assetbundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/spriteset/sprite_boss_baiguiju.unity3d");
        stopwatch.Stop(); //  停止监视
        System.TimeSpan timespan = stopwatch.Elapsed;
        UnityEngine.Debug.Log("C# costTime:" + timespan.TotalMilliseconds);


        double hours = timespan.TotalHours; // 总小时
        double minutes = timespan.TotalMinutes;  // 总分钟
        double seconds = timespan.TotalSeconds;  //  总秒数
        double milliseconds = timespan.TotalMilliseconds;  //  总毫秒数
    }
	
	// Update is called once per frame
	void Update () {
		
	}
}


1.1打包结果以及加载速度对比

由于时间有限,仅限于window测试,下来有空的时候在真机上测试一下。

压缩方式 ab包容量 加载消耗时间  
BuildAssetBundleOptions.None  lzma压缩 180 KB 13.4731ms  
BuildAssetBundleOptions.ChunkBasedCompression lz4压缩 217 KB 0.8209ms  
 BuildAssetBundleOptions.UncompressedAssetBundle 不压缩 1M 0.7838ms  
从结论可以看出,lz4和不压缩的打包方式加载消耗时间几乎一样,而包体lz4也比lzma小了很多。所以推荐使用lz4的压缩方式。


2.AssetBundle.Unload注意事项。

 例如某个UI 打成了AB包   a.unity3d ,该资源引用某图集b.unity3d。

2.1重构起始做法(伪代码)

     AssetBundle ab_a = LoadAssetbundle(a.unity3d)//同时递归加载了依赖 b.unity3d  ab_b

    GameObject prefab = ab_a.load() as GameObject;

     GameObject  ui= Instantiate(prefab) as GameObject;

扫描二维码关注公众号,回复: 1552794 查看本文章

    SetUiInfo();

    ab_a.Unload(false) ; //同时递归也让ab_b卸载掉。

2.2问题所在

这种做法的结果是 UI 上很多image图片错乱,明显是Image没正确加载到Sprite。一番纠结之后得出结论是

Instantiate 操作并不是立即完成,需要有几帧的时间才能加载完成。

2.3正确做法,不一定好,有更好的方案望赐教。

开启协程,让加载ab完成后1秒在执行卸载操作。


    



猜你喜欢

转载自blog.csdn.net/jason1285837980/article/details/80626352