unity 中 AssetBundle打包及使用总结(WebGL)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mansir123/article/details/84951692

资源打包,教程很多。但,适合自己项目的打包又有几个?None
打包注意点:
(1)资源尽量分文件夹放置,便于打包资源的管理
(2)打包相对独立资源
(3)打包时,尽量只打包素材,且大小控制在10M左右,避免影响下载速度
(4)打入包的实例化物体,在其他脚本被引用的时候,通过查找方式(名称会多个“(clone)”)。且实例化一定要比引用要早,避免出现访问空对象的问题。尽量实例化在Awake中,引用在Start中。
(5)共用资源、私有资源配合打包
共有资源打包,可用初始化代码统一管理。比如房间、人、治疗巾等。但是需要进入程序即开始异步下载,以免影响各常见的使用。
私有资源在进入对应场景时再下载,避免资源浪费;在场景卸载时,一定卸载私有资源。
(6)如果有 AssetBoudle的使用,保证在发布时,不勾选“Strip Engine Code*”,但是无用代码一定清理干净。

WebGl平台的资源打包:
一、标记资源(AssetBoudle名称,如xx.ab )
二、创建以下代码,放入“Asset—Editor”路径中

[MenuItem("AssetsBoundle/Build AssetBoudles")]
    static void BuildAllAssetBoundles()
    {
        string strDir = "AssetBoundles";
    if(Directory.Exists(strDir)==false)
    {
        Directory.CreateDirectory(strDir);
    }
    BuildPipeline.BuildAssetBundles(strDir, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.WebGL);
 }

核心是BuildAssetBundles(strDir, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.WebGL);

采用Chunk的编译方法,是为了WebGl的下载、编译快速。平台要选择WebGL。
三、已打包的内容放置到服务器。
有可能服务器需要设置下(1) 文件格式的类型(2)跨域访问 (3)访问权限
四、运行程序时,启动协程,下载、加载对应资源

    public List<string> bundleToLoadList = new List<string>();  //要下载、加载的所有资源路径
    public List<AssetBundle> bundlesLoadedList = new List<AssetBundle>(); //已下载的资源列表
    Dictionary<string, Object> allObjs=new Dictionary<string,Object>();  //所有预设体字典
    List<Object> objsList = new List<Object>(); //所有预设体
    public string strABUrl=@"http://192.168.1.110:80/boundles/"; //下载地址


	void Start () {
        StartCoroutine(load());
	}
    IEnumerator load()
    {

        foreach(string strBundle in bundleToLoadList)
        {
            string strurl = strABUrl + strBundle;
            Debug.Log(strurl+" Time:"+Time.time);
		//用using的方式,为了让web自行释放
             using (WWW bundleW = new WWW(strurl)) 
             {
                 yield return bundleW; //下载过程

                 if (bundleW.isDone && bundleW.error == null)
                 {
                     Debug.Log(bundleW.assetBundle.name + " downloaded success!" + " Time:" + Time.time);
                     AssetBundle assetBd = bundleW.assetBundle;
                     bundlesLoadedList.Add(assetBd);
                     Debug.Log("bundle name:" + assetBd.name);

                     Object[] objs = assetBd.LoadAllAssets();  //加载过程
                     Debug.Log("loaded success!" + " Time:" + Time.time);
                     foreach (Object obj in objs)
                     {
                         if (!allObjs.ContainsKey(obj.name))
                         {
                             if (obj.GetType() == typeof(GameObject))
                                 allObjs.Add(obj.name, obj);
                         }
                         else
                             Debug.Log("aready exist  asset :" + obj.name + " type:" + obj.GetType() + " with type:" + allObjs[obj.name].GetType());

                         objsList.Add(obj);
                     }
                 }
                 else
                     Debug.Log("down load failed!--" + strBundle);
             }
        }
    }
//强制卸载所有资源
 public void ForceUnLoadAll()
    {
        if (bundlesLoadedList.Count == 0)
            return;

        for (int i = 0; i < bundlesLoadedList.Count;i++ )
        {
            if(bundlesLoadedList[i]!=null)
            {
                bundlesLoadedList[i].Unload(true);
                bundlesLoadedList[i] = null;
            }
        }
        for (int i = 0; i < objsList.Count; i++)
        {
            objsList[i] = null;
        }
        objsList.Clear();
        foreach (KeyValuePair<string, Object> obj in allObjs)
        {
            allObjs[obj.Key] = null;
        }
        allObjs.Clear();
    }

五、在需要实例化的地方,进行实例化

 public List<string> gameobjectsToInstantiate = new List<string>(); //需要的加载预设体的名称列表
  BundleLoadMgr bundleLoadMgr = null; //资源加载器对象(上面代码的类)
  void Awake () {
        bundleLoadMgr = GameObject.Find("BundleLoadMgr").GetComponent<BundleLoadMgr>();
        StartCoroutine(InstanceInstantiate());
       // InstanceInOneLine();
	}
   IEnumerator InstanceInstantiate()
    {
        if (bundleLoadMgr != null)
        {
            foreach (string strObj in gameobjectsToInstantiate)
            {
                Object obj = null; 
                ////确保加载上后,再开始初始化所有物体
                while(obj==null)
                {
                  obj=   bundleLoadMgr.GetGameobjectAssetByName(strObj);
                  yield return obj;
                }
                    yield return Instantiate(obj);
            }
        }
    }

协程实例化的方式,可能会造成其他脚本调用到本预设体时为空的问题。也可以在主线程实例化这些预设体,但是如果之前未下载完成的话,可能会卡住线程。两种方法各有利弊。尽量让预设体有自己的独立性,最起码预设体外的尽量少引用该预设体。

最后记着销毁无用的资源。

猜你喜欢

转载自blog.csdn.net/mansir123/article/details/84951692