李虹霖

 

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);
    }
}

 

posted on 2015-11-26 11:16  lol霖  阅读(1222)  评论(0编辑  收藏  举报

导航