首先创建一个单例类,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