Unity5 AssetBundle 打包以及加载
using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEditor; using System.IO; public class BuildAssetBundle : Editor { //需要打包的路径,根据项目具体需求自己定 private static string assetPath = "AllAssets"; //导出包路径 private static string AssetBundleOutPsth = "Assets/StreamingAssets"; //保存需要打包的资源路径 private static List<string> assetPathList = new List<string>(); //需要打包的资源后缀 private static Dictionary<string, string> asExtensionDic = new Dictionary<string, string> (); [MenuItem("Assets/BuildAssetBundle")] private static void BuildAssetBundleSource() { assetPathList.Clear (); //根据不同平台拼接不同平台导出路径 string outPsth = Path.Combine (AssetBundleOutPsth, Plathform.GetPlatformFolder(EditorUserBuildSettings.activeBuildTarget)); GetDirs(Application.dataPath + "/" + assetPath); BuildAsset (outPsth); } //添加需要打包资源的后缀 private static void SetASExtensionDic () { asExtensionDic.Clear (); asExtensionDic.Add (".prefab", ".unity3d"); asExtensionDic.Add (".mat", ".unity3d"); asExtensionDic.Add (".png", ".unity3d"); } //遍历制定文件夹获取需要打包的资源路径 private static void GetDirs(string dirPath) { foreach (string path in Directory.GetFiles(dirPath)) { // 通过资源后缀判断资源是否为需要打包的资源 if (asExtensionDic.ContainsKey(System.IO.Path.GetExtension(path))) { //将需要打包的资源路径添加到打包路劲中 assetPathList.Add(path); } } if (Directory.GetDirectories(dirPath).Length > 0) //遍历所有文件夹 { foreach (string path in Directory.GetDirectories(dirPath)) { //使用递归方法遍历所有文件夹 GetDirs(path); } } } //清除已经打包的资源 AssetBundleNames private static void ClearAssetBundlesName() { int length = AssetDatabase.GetAllAssetBundleNames ().Length; Debug.Log (length); string[] oldAssetBundleNames = new string[length]; for (int i = 0; i < length; i++) { oldAssetBundleNames[i] = AssetDatabase.GetAllAssetBundleNames()[i]; } for (int j = 0; j < oldAssetBundleNames.Length; j++) { AssetDatabase.RemoveAssetBundleName(oldAssetBundleNames[j],true); } } //打AS包 private static void BuildAsset(string outPath) { //遍历获取到的打包资源路径 for (int i = 0; i < assetPathList.Count; i ++) { string asPath = assetPathList[i]; //通过资源路径来获取需要打包的资源 AssetImporter assetImporter = AssetImporter.GetAtPath(asPath); if (assetImporter == null) { continue; } // 从此处(assetPath = "AllAssets")截取路径 string assetName = asPath.Substring(asPath.IndexOf(assetPath)); //替换后缀名 assetName = assetName.Replace(Path.GetExtension(assetName), ".unity3d"); //设置打包资源的名字包括后缀 assetImporter.assetBundleName = assetName; } //如果不存在到处路径文件,创建一个 if (!Directory.Exists (outPath)) { Directory.CreateDirectory(outPath); } //打包 BuildPipeline.BuildAssetBundles (outPath, 0, EditorUserBuildSettings.activeBuildTarget); //刷新资源路径,避免生成的文件不显示 AssetDatabase.Refresh (); } } //根据切换的平台返回相应的导出路径 public class Plathform { public static string GetPlatformFolder(BuildTarget target) { switch (target) { case BuildTarget.Android: //Android平台导出到 Android文件夹中 return "Android"; case BuildTarget.iOS: return "IOS"; case BuildTarget.WebPlayer: return "WebPlayer"; case BuildTarget.StandaloneWindows: case BuildTarget.StandaloneWindows64: return "Windows"; case BuildTarget.StandaloneOSXIntel: case BuildTarget.StandaloneOSXIntel64: case BuildTarget.StandaloneOSXUniversal: return "OSX"; default: return null; } } }
操作如下,以项目为例
在 StreamingAssets文件夹下生成AB文件
打比完毕,每个资源自动打包出两个文件
下面是加载,封装了一下加载代码如下
using UnityEngine; using System.Collections; using System.Collections.Generic; using System; using System.IO; // 回调方法 public delegate void CallBack(UnityEngine.Object obj); // AS 文件只能加载一次,重复加载出错,两种方案, // 一、加载后卸载,下次需要使用时重新加载, // 二、加载后将AS保存起来,下载加载相同AS时直接取出来使用 public class LoadAssetBundle{ //单例 public static readonly LoadAssetBundle Instance = new LoadAssetBundle(); private string path = Application.streamingAssetsPath; //保存加载的AS private Dictionary<string, AssetBundle> assetBundleRefDic = new Dictionary<string, AssetBundle>(); //PC本地资源需加上 "file://" private string GetThePathWithPlathform { get { if (Application.isEditor) { return "file://" + path; } else { return path; } } } // 加载后释放 // assetPath 加载资源路径 // assetName 资源名 // type 加载资源类型 // callBack 加载完成回调 // isUnload 加载后是否卸载 public IEnumerator Load(string assetPath, string assetName, Type type, CallBack callBack, bool isUnload) { string loadpath = GetThePathWithPlathform; string url = Path.Combine(loadpath, assetPath); AssetBundle ab = GetASFromUrl (url); if (ab != null) { GetObject (ab, assetName, type, callBack, isUnload); yield return null; } else { WWW www = WWW.LoadFromCacheOrDownload (url, 0); yield return www; if (!string.IsNullOrEmpty (www.error)) { Debug.LogError (www.error); yield return null; } else { ab = www.assetBundle; GetObject ( ab, assetName, type, callBack, isUnload); if (!isUnload) { if (!assetBundleRefDic.ContainsKey(url)) { Debug.Log("add"); assetBundleRefDic.Add(url, ab); } } } } } //从 AssetBundle 中将资源加载出来 private void GetObject(AssetBundle ab, string assetName, Type type, CallBack callBack, bool isUnload) { UnityEngine.Object obj = ab.LoadAsset (assetName, type); if (callBack != null) { callBack(obj); // 回调 } if (isUnload) { // 加载资源后从内存中卸载 ab.Unload (true); } } //根据地址从字典中获取 AssetBundle private AssetBundle GetASFromUrl(string url) { AssetBundle ab = null; if (assetBundleRefDic.TryGetValue (url, out ab)) { return ab; } return null; } }
//调用如下 using UnityEngine; using System.Collections; public class Test : MonoBehaviour { // Update is called once per frame void Update () { if (Input.GetKeyDown (KeyCode.A)) { string loadPath = "Android/allassets/gameobject.unity3d"; string asName = "gameobject"; StartCoroutine(LoadAssetBundle.Instance.Load(loadPath, asName, typeof(GameObject), CallBack, true)); } if (Input.GetKeyDown (KeyCode.D)) { string loadPath = "Android/allassets/gameobject.unity3d"; string asName = "gameobject"; StartCoroutine(LoadAssetBundle.Instance.Load(loadPath, asName, typeof(GameObject), CallBack, false)); } } private void CallBack(UnityEngine.Object obj) { Debug.Log (obj.name); GameObject.Instantiate ((GameObject)obj); } }