AssetBundle5.3.4包加载

原创 2016年05月31日 09:04:42

首先创建一个单例类,wiki上面也有例子,直接Copy进行简单修改:

using UnityEngine;

public class Singleton<T> : MonoBehaviour where T : MonoBehaviour //因为继承MonoBehaviour的物体不能使用new()来构造实例 所以这里只能用MonoBehaviour
{
    private static T instance; //实例目标对象

    protected virtual void Awake()
    {
        this.CheckInstance(); //觉醒检查
    }

    protected bool CheckInstance()//是否唯一,不是就销毁多余的目标,防止目标有多个挂载在其他gameobject上。
    {
        if (this == Singleton<T>.Instance)
        {
            return true;
        }
        UnityEngine.Object.Destroy(this);
        return false;
    }

    public static T Instance
    {
        get
        {
            if (Singleton<T>.instance == null)
            {
                Singleton<T>.instance = (T)UnityEngine.Object.FindObjectOfType(typeof(T));// 如果对象没实例化,则为空
                if (Singleton<T>.instance == null)
                {
                    Debug.LogError(typeof(T) + " was no attached GameObject");
                }
            }
            return Singleton<T>.instance;
        }
    }
}

接下来建立一个Builder类用来给我们需要打包的指定文件夹的中资源加上assetname并打包成assetbundle,参考我前面的文章:http://blog.csdn.net/jeanshaw/article/details/51438284

下面就是下载我们的包,放在了data文件夹外面 ,因为这样方便替换,不需要重新打包发布软件包出来,相对方便。

</pre><p><pre name="code" class="html">using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;

public class LoadPrefab : MonoBehaviour
{
    //public bool allowTochangScene = false;
    public static LoadPrefab instance = null;
    private Dictionary<string, GameObject> GameObjectPool = new Dictionary<string, GameObject>();
    private string filePath = "./" ;

    XmlDocument xmlDoc = new XmlDocument();
    Queue<string> needLoadQueue = new Queue<string>();
    Queue<string> needLoadQueuePrivate = new Queue<string>();

    public GameObject parentGo;
    public GameObject gamePoolPrefab;

    void Awake()
    {
        Debug.Log("开始时间 :" + Time.time);
        instance = this;
        LoadPrefabs(SceneLoadMag.instance.senceNameActive);       
        
    }

    void LoadPrefabs(string name)
    {

        filePath = Application.streamingAssetsPath +"/"+ name + ".xml";
        Debug.Log(filePath);
       
        byte[] rawdata = File.ReadAllBytes(filePath);
        using (var stream = new MemoryStream(rawdata))
        {
            var formatter = new System.Xml.Serialization.XmlSerializer(typeof(XmlDocument));
            xmlDoc = (XmlDocument)formatter.Deserialize(stream);
            stream.Close();
        }

       
        XmlNode sceneposNode = xmlDoc.SelectSingleNode(name);
        Vector3 scenePosition = StringCommon.Instance.GetVector3Value(sceneposNode.Attributes["Position"].Value);
        parentGo.name = SceneLoadMag.instance.senceNameActive;
        parentGo.transform.localPosition = scenePosition;

        XmlNodeList prefabList = xmlDoc.SelectNodes(name + "/SencePrefab/PrefabNode ");
        XmlNodeList prefabPrivateList = xmlDoc.SelectNodes(name + "/PrivatePrefab/PrefabNode");
        
        foreach (XmlNode preNode in prefabList)
        {
            needLoadQueue.Enqueue(StringCommon.Instance.GetStringPath(preNode.Attributes["name"].Value));
        }
        foreach (XmlNode priNode in prefabPrivateList)
        {
            needLoadQueuePrivate.Enqueue(StringCommon.Instance.GetStringPath(priNode.Attributes["name"].Value));
        }

        Invoke("LoadPrivate", 0.05f);
    }

    #region 下载私有资源
    void LoadPrivate()
    {
        Debug.Log("下载私有时间 :" + Time.time);
        if (needLoadQueuePrivate.Count > 0)
        {
            string needLoadAssetName = needLoadQueuePrivate.Dequeue();
            AssetBundleLoaderMgr.Instance.LoadAssetBundle(needLoadAssetName, (obj) =>
            {
                GameObject go = GameObject.Instantiate(obj) as GameObject;
                PrivatObjList.Add(obj);
                go.transform.position = Vector3.zero;               
                go.transform.SetParent(parentGo.transform);
                Invoke("LoadPrivate", 0.05f);
            }, SceneLoadMag.instance.senceNameActive);//另外一个获取表名的类中的名字信息
        }
        else
        {
            Debug.Log("Private already loaded");
            Debug.Log("私有下载完时间 :"  + Time.time);
            Load();
        }
    }

    #endregion
    void Load()
    {
        if (needLoadQueue.Count > 0)
        {
            string needLoadAssetName = needLoadQueue.Dequeue();
            AssetBundleLoaderMgr.Instance.LoadAssetBundle(needLoadAssetName, (obj) =>
            {              
                GameObject go = GameObject.Instantiate(obj) as GameObject;
                go.transform.parent = gamePoolPrefab.transform;               
                int index = needLoadAssetName.LastIndexOf("/");
                string assetName = needLoadAssetName.Substring(index + 1);
                //加载出来的GameObject放到GameObjectPool存储
                GameObjectPool.Add(assetName, go);              
                Invoke("Load", 0.05f);
            }, "WindowsPublic");
        }
        else
        {
            Debug.Log("all finished");
            Debug.Log("时间 :" + Time.time);
            StartCoroutine(ReadXml());            
        }
    }

    IEnumerator ReadXml()
    {
        int insCount = 0;
        XmlNodeList elementList = xmlDoc.SelectNodes(SceneLoadMag.instance.senceNameActive+"/SenceElement/SenceNode1");

        foreach (XmlNode node in elementList)
        {
            GameObject obj = new GameObject();
            obj.transform.parent = parentGo.transform;
            obj.name = node.Attributes["name"].Value; 
            obj.transform.localPosition =StringCommon.Instance.GetVector3Value(node.Attributes["Position"].InnerText);
            obj.transform.localEulerAngles = StringCommon.Instance.GetVector3Value(node.Attributes["EulerAngles"].InnerText);
          
            XmlNodeList childElementList = node.SelectNodes("SenceNode2 ");
            foreach (XmlNode childNode in childElementList)
            {
                string prefabName = childNode.Attributes["Prefab"].Value;
                GameObject go = Instantiate(GameObjectPool[prefabName]) as GameObject;
                go.transform.parent = obj.transform;
                go.name = childNode.Attributes["name"].Value;
                go.transform.localPosition = StringCommon.Instance.GetVector3Value(childNode.Attributes["Position"].InnerText);
                go.transform.localEulerAngles = StringCommon.Instance.GetVector3Value(childNode.Attributes["EulerAngles"].InnerText);

                MeshRenderer render = go.GetComponent<MeshRenderer>();
                render.lightmapIndex = int.Parse(childNode.Attributes["LightMapIndex"].Value);
                render.lightmapScaleOffset = StringCommon.Instance.GetVector4Value(childNode.Attributes["LightMapScale"].InnerText);

                insCount++;
                if (insCount > 100)//一次加载100个,不然文件太大会卡,根据实际情况数值可以调整
                {
                    insCount = 0;
                    yield return null;
                }
            }
        }
        Debug.Log("All prefabs is loaded");
        Destroy(gamePoolPrefab);
       
    }
 
}
下面需要一个进行加载的管理类,如下

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.IO;

public class AssetBundleLoaderMgr : Singleton<AssetBundleLoaderMgr>
{
    static string assetTail = ".unity3d";
    private string privateStr = SceneLoadMag.instance.senceNameActive;
    AssetBundleCreateRequest asset;
    #region LoadAssetBundle
    /// <summary>
    /// 加载目标资源
    /// </summary>
    /// <param name="name"></param>
    /// <param name="callback"></param>
    
    public void LoadAssetBundle(string name, Action<UnityEngine.Object> callback,string str)
    {
        //Debug.Log(name);
        Action<List<AssetBundle>> action = (depenceAssetBundles) =>
        {
            name = name + assetTail;   
            string realName = str + "/" + name;  
            LoadResReturnWWW(realName, (www) =>
            {
                int index = realName.LastIndexOf("/");
                string assetName = realName.Substring(index + 1);
                assetName = assetName.Replace(assetTail, "");
                AssetBundle assetBundle = www.assetBundle;
                UnityEngine.Object obj = assetBundle.LoadAsset(assetName);//LoadAsset(name),这个name没有后缀,eg:panel
                
                //卸载资源内存
                assetBundle.Unload(false);
                for (int i = 0; i < depenceAssetBundles.Count; i++)
                {
                    depenceAssetBundles[i].Unload(false);
                }
                //加载目标资源完成的回调
                callback(obj);
            });
        };
        LoadDependenceAssets(name, action,str);
    }

    /// <summary>
    /// 加载目标资源的依赖资源
    /// </summary>
    /// <param name="targetAssetName"></param>
    /// <param name="action"></param>
    private void LoadDependenceAssets(string targetAssetName, Action<List<AssetBundle>> action,string str)
    {
        Debug.Log("要加载的目标资源:" + targetAssetName);//ui/panel.unity3d
        Action<AssetBundleManifest> dependenceAction = (manifest) =>
        {
            List<AssetBundle> depenceAssetBundles = new List<AssetBundle>();//用来存放加载出来的依赖资源的AssetBundle

            string[] dependences = manifest.GetAllDependencies(targetAssetName);
            //Debug.Log("依赖文件个数:" + dependences.Length);
            int length = dependences.Length;
            int finishedCount = 0;
            if (length == 0)
            {
                //没有依赖
                action(depenceAssetBundles);
            }
            else
            {
                //有依赖,加载所有依赖资源
                for (int i = 0; i < length; i++)
                {
                    string dependenceAssetName = dependences[i];
                    dependenceAssetName = str + "/" + dependenceAssetName;//eg:Windows/altas/heroiconatlas.unity3d
                    //加载,加到assetpool
                    LoadResReturnWWW(dependenceAssetName, (www) =>
                    {
                        int index = dependenceAssetName.LastIndexOf("/");
                        string assetName = dependenceAssetName.Substring(index + 1);
                        assetName = assetName.Replace(assetTail, "");
                        AssetBundle assetBundle = www.assetBundle;
                        UnityEngine.Object obj = assetBundle.LoadAsset(assetName);
                        //assetBundle.Unload(false);
                        depenceAssetBundles.Add(assetBundle);

                        finishedCount++;

                        if (finishedCount == length)
                        {
                            //依赖都加载完了
                            action(depenceAssetBundles);
                        }
                    });
                }
            }
        };
        LoadAssetBundleManifest(dependenceAction,str);
    }

    /// <summary>
    /// 加载AssetBundleManifest
    /// </summary>
    /// <param name="action"></param>
    private void LoadAssetBundleManifest(Action<AssetBundleManifest> action,string str)
    {
        //string manifestName = this.GetRuntimePlatform();
        string manifestName = str;
        manifestName = manifestName + "/" + manifestName;//eg:Windows/Windows
        LoadResReturnWWW(manifestName, (www) =>
        {
            AssetBundle assetBundle = www.assetBundle;
            UnityEngine.Object obj = assetBundle.LoadAsset("AssetBundleManifest");
            assetBundle.Unload(false);
            AssetBundleManifest manif = obj as AssetBundleManifest;
            action(manif);
        });
    }
    #endregion
   
    #region ExcuteLoader
    //public void LoadResReturnWWW(string name, Action<WWW> callback)
    public void LoadResReturnWWW(string name, Action<AssetBundleCreateRequest> callback)
    {      
        string path = "./"+name;    
        //Debug.Log("加载:" + path);
        StartCoroutine(LoaderRes(path, callback));  
    }

    IEnumerator LoaderRes(string path, Action<AssetBundleCreateRequest> callback)
    {
        FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
        byte[] assetBytes = new byte[fs.Length];
        fs.Read(assetBytes, 0, (int)fs.Length);
        fs.Close();
        asset = AssetBundle.LoadFromMemoryAsync(assetBytes);
        yield return asset;

        if (asset.isDone)
        {
            callback(asset);
        }    
    }
    #endregion



版权声明:本文为博主原创文章,未经博主允许不得转载。

Unity5.x AssetBundle打包和加载示例

  • 2016年04月27日 11:30
  • 923KB
  • 下载

Unity3D游戏开发之使用AssetBundle和Xml实现场景的动态加载

各位朋友,大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei。 引言今天我想和大家聊聊在Unity3D中关于场景的动态加载的问题。众所周知在Un...

Unity3d发布Android版通过WWW加载本地AssetBundle资源

不久之前买了小米平板,就想着用Unity3d做个小游戏放在平板上玩玩,匆匆做了个资源加载界面就发布apk到平板上,结果提示资源加载失败,找不到资源文件。在网上找了半天资料都没解决问题,最后发现自己犯了...

Unity游戏开发使用Assetbundle加载场景的实战

之前有一篇文章中我们相惜讨论了Assetbundle的原理,如果对原理还不太了解的朋友可以看这一篇文章:Unity游戏开发使用Assetbundle加载场景的原理 本篇文章我们将说说assetbund...

unity动态加载之AssetBundle原理

Assetbundle 是Unity Pro提供提供的功能,它可以把多个游戏对象或者资源二进制文件封装到Assetbundle中,提供了封装与解包的方法使用起来很便利。 1.预设         ...

Unity3d热更新全书-资源加载(一):从AssetBundle说起

原文链接:http://www.unity.5helpyou.com/3164.html   本篇unity3d教程我们来继续探讨unity热更新全书,先从资源加载说起,Unity3D动态...

Unity3D之AssetBundle资源加载封装

http://www.luzexi.com/unity3d%E4%B9%8Bassetbundle%E8%B5%84%E6%BA%90%E5%8A%A0%E8%BD%BD%E5%B0%81%E8%A3...

AssetBundle的制作与加载

【AssetBundle简介】 设计原理:一个资源可以分到多个包里;多个资源可以打进一个包里 可以实时从任意位置 加载资源包 运行时加载,将资源打成包,自己控制整个资源的管理,加载效率稍微差 要自己控...

[Unity3d]安卓无法加载assetbundle的问题

前几天做了AssentBundle的例子,遇到了问题,在论坛上问了三天都没人解答,最后在一个朋友的帮助下解决了。下面介绍AssentBundle。 AssetBundles让你通过WWW类流式加...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:AssetBundle5.3.4包加载
举报原因:
原因补充:

(最多只允许输入30个字)