Unity AssetBundle管理(一)

来源:互联网 发布:lol美服加速器免费mac 编辑:程序博客网 时间:2024/09/21 06:18

AssetBundle 是一种压缩文件,压缩时用到的压缩格式可以在打bundle的时候指定,BuildPipeline.BuildAssetBundles方法第二个参数可以指定压缩格式。

使用AssetBundle流程分为两部

1.把资源打成AssetBundle

先把资源(纹理,材质,模型)指定一个AssetBundle名字和后缀


然后调用BuildPipeline.BuildAssetBundles方法把资源打成AssetBundle

2.从AssetBundle中加载资源

常用的方式为用WWW先把AssetBundle下载下来(通过网络或者是从本地加载),然后从WWW中加载出来AssetBundle,然后从AssetBundle中加载出来资源,然后再把资源实例化(如果是纹理图片之类的可以直接使用)

3.关于内存

先来看看一个AssetBundle资源占的内存情况

用WWW下载完后,WWW会保留一份缓存,从WWW中加载出来AssetBundle后会有一份AssetBundle的缓存,从AssetBundle中加载出来资源后有一份资源的缓存,把资源实例化后会有一份实例化的缓存。所以我们要管理好这些缓存,及时把没用的清理掉。


我们先来写一个自动打AssetBundle的工具

首先创建一个文件夹 Art,我们把项目中需要的资源按类型放到这个文件夹


我们会把这里面的资源的AssetBundle的名字标记为它所在的文件夹的名字

自动标记名字和打Assetbundle的代码如下:

using UnityEngine;using System.Collections;using UnityEditor;using System.IO;using System.Collections.Generic;public class AssetBundleEditor {    static string outPath = null;    static string assetFullPath = Application.dataPath + "/Art/";    static string assetPath = @"Assets/Art/";    [MenuItem("Itools/BuildeAssetBundle")]    public static void BuildeAssetBundle() {        outPath = IPathTools.GetEditeABOutPath();        if (Directory.Exists(outPath)) {            DirectoryInfo di = new DirectoryInfo(outPath);            di.Delete(true);        }        Debug.Log("outPath "+ outPath);        Directory.CreateDirectory(outPath);        BuildPipeline.BuildAssetBundles(outPath, BuildAssetBundleOptions.None, EditorUserBuildSettings.activeBuildTarget);        AssetDatabase.Refresh();    }    [MenuItem("Itools/MarkAssetBundle")]    public static void MarkAssetBundle() {        AssetDatabase.RemoveUnusedAssetBundleNames();        assetFullPath = FixedWindowsPath(assetFullPath);        Dictionary<string, string> bundlePathDic = new Dictionary<string, string>();        DirectoryInfo dir = new DirectoryInfo(assetFullPath);        FileSystemInfo[] fileSystemInfo = dir.GetFileSystemInfos();        for (int i=0;i< fileSystemInfo.Length;i++) {            FileSystemInfo tmpFile = fileSystemInfo[i];            if (tmpFile is DirectoryInfo) {                string tmpPath = Path.Combine(assetFullPath, tmpFile.Name);                //SceneOverView(tmpPath);                ErgodicDirectory(tmpPath, bundlePathDic);            }        }        AssetDatabase.Refresh();    }    //遍历目录    public static void ErgodicDirectory(string path, Dictionary<string, string> bundlePathDic) {        DirectoryInfo dir = new DirectoryInfo(path);        if (dir != null)        {            FileSystemInfo[] fileInfo = dir.GetFileSystemInfos();            for (int i = 0; i < fileInfo.Length; i++) {                FileSystemInfo tmpFile = fileInfo[i];                string tmpPath = Path.Combine(path, tmpFile.Name);                                if (tmpFile is DirectoryInfo)                {                                        ErgodicDirectory(tmpPath, bundlePathDic);                }                else {                    SetAssetBundleName(tmpFile, bundlePathDic);                }            }        }        else        {            Debug.Log("this path is not exit");        }    }    //设置assetbundle name    public static void SetAssetBundleName(FileSystemInfo fileSystemInfo,Dictionary<string, string> bundlePathDic) {        FileInfo fileInfo = fileSystemInfo as FileInfo;        if (fileInfo.Extension == ".meta")        {            return;        }                string assetBundleName = fileInfo.Directory.Name;        string fullPath = FixedWindowsPath(fileInfo.DirectoryName);        int tmpCount1 = fullPath.Length;        int tmpCount2 = assetFullPath.Length;        int assetPathCount = tmpCount1 - tmpCount2;        string assetBundlePath = fullPath.Substring(tmpCount2, assetPathCount);        string path = assetPath + assetBundlePath+"/" + fileInfo.Name;        Debug.Log("path "+ path);        AssetImporter importer = AssetImporter.GetAtPath(path);        //设置assetbundle name        importer.assetBundleName = assetBundleName;                //设置assetbundle 后缀        if (fileInfo.Extension == ".unity")        {            importer.assetBundleVariant = "u3d";        }        else        {            importer.assetBundleVariant = "ab";        }        //保存bundle的相对路径        int startIndex = fileInfo.FullName.IndexOf("Art");        int endIndex = fileInfo.FullName.Length;        int count = endIndex - startIndex;        string bundlePath = fileInfo.FullName.Substring(startIndex, count);        if (!bundlePathDic.ContainsKey(assetBundleName)) {            bundlePathDic.Add(assetBundleName, bundlePath);        }    }    //修正路径    public static string FixedWindowsPath(string path)    {        path = path.Replace("\\","/");        return path;    }}

其中函数MarkAssetBundle,ErgodicDirectory,SetAssetBundleName为标记AssetBundle名字的

函数BuildeAssetBundle为打AssetBundle的

这时我们会在unity菜单中看到这两个工具



加载AssetBundle

先来看一下我们的例子


Art下有三个文件夹Load,Material,Texture,按照我们的规则这三个文件夹下的资源的AssetBundle的名字和这三个文件夹一样。

这样我们用上面写的自动打AssetBundle的工具就打出了三个AsserBundle包分别是load.ab,material.ab,texture.ab,其中后缀.ab是在自动打AssetBundle的工具代码中指定的。其中正方体Cube在load.ab包中,材质m_Material在material.ab中,纹理detail在texture.ab中。

其中正方体Cube用的材质是m_Material,材质m_Material用的纹理是detail。

我们打出的AssetBundle如下:


在文件夹中会看到这些东西


其中以.ab(我们自己指定的)结尾的是我们的AssetBundle包,以.manifest结尾的是该AssetBundle的信息


因为我们的正方体Cube用的材质是m_Material,而m_Material在material.ab中,所以load.ab依赖material.ab

打AssetBundle后会有一个和AssetBundle输出目录一样名字的AssetBundle和.manifest文件,因为我们最终把AssetBundle打到目录StreamingAssets/windows中了,所以我们会看到这样两个文件



其中windows.manifest文件中记录了我们所有的AssetBundle信息和依赖关系



假如我们想从load.ab中加载出来立方体Cube,因为立方体Cube依赖material.ab,所以我们要把material.ab加载出来,又因为material.ab依赖texture.ab,所以我们要把texture.ab加载出来


我们先写一个简单的加载资源的代码,在下一章中我们会把所有AssetBundle的依赖和被依赖关系都管理起来,也会写出对AssetBundle缓存的清理的接口

using UnityEngine;using System.Collections;using System.Collections.Generic;public class Test : MonoBehaviour {    string manifestPath = "";    public AssetBundle manifestLoader;    public AssetBundleManifest assetManifest;    public Dictionary<string, AssetBundle> abDic = new Dictionary<string, AssetBundle>();    bool isManifestFinished = false;    // Use this for initialization    void Start()    {        manifestPath = IPathTools.GetABManifestName();        StartCoroutine(LoadManifest());        string path = IPathTools.GetAssetBundlePath() + "/load.ab";        StartCoroutine(LoadAssetBundle(path));    }    public IEnumerator LoadManifest() {        WWW manifest = new WWW(manifestPath);        yield return manifest;        if (!string.IsNullOrEmpty(manifest.error))        {            Debug.Log(manifest.error);        }        else {            if (manifest.progress >= 1.0f) {                isManifestFinished = true;                Debug.Log("加载manifest成功");                manifestLoader = manifest.assetBundle;                assetManifest = manifestLoader.LoadAsset("AssetBundleManifest") as AssetBundleManifest;                //输出所有的AssetBundle的名字                string[] str = assetManifest.GetAllAssetBundles();                for (int i = 0; i < str.Length; i++)                {                    Debug.Log(str[i]);                }            }        }    }    //加载AssetBundle    public IEnumerator LoadAssetBundle(string path)    {        if (!isManifestFinished)        {            yield return null;        }        WWW www = new WWW(path);        yield return www;        Debug.Log(path);        if (!string.IsNullOrEmpty(www.error))        {            Debug.Log(www.error);        }        else        {            AssetBundle ab = www.assetBundle;            if (!abDic.ContainsKey(ab.name))            {                abDic.Add(ab.name, ab);                Debug.Log("abName " + ab.name);            }            string[] dependencies = assetManifest.GetAllDependencies(ab.name);            for (int i = 0; i < dependencies.Length; i++)            {                if (!abDic.ContainsKey(dependencies[i]))                {                    string abPath = IPathTools.GetAssetBundlePath() + "/" + dependencies[i];                    yield return LoadAssetBundle(abPath);                }            }            //测试实例化立方体Cube            if (ab.name.Equals("load.ab"))            {                AssetBundle mainAb = abDic["load.ab"];                Object o = mainAb.LoadAsset("Cube");                Instantiate(o, Vector3.zero, Quaternion.identity);            }        }        www.Dispose();    }    //循环加载AssetBundle依赖    public IEnumerator LoadDependenciesAssetBundle(string path) {        if (!isManifestFinished)        {            yield return null;        }        WWW www = new WWW(path);        yield return www;        Debug.Log("依赖 "+path);        if (!string.IsNullOrEmpty(www.error))        {            Debug.Log(www.error);        }        else {            AssetBundle ab = www.assetBundle;            if (!abDic.ContainsKey(ab.name))            {                abDic.Add(ab.name, ab);                Debug.Log("依赖abName " + ab.name);            }            string[] dependencies = assetManifest.GetAllDependencies(ab.name);            for (int i = 0; i < dependencies.Length; i++)            {                string abPath = IPathTools.GetAssetBundlePath() + "/" + dependencies[i];                yield return LoadDependenciesAssetBundle(abPath);            }        }    }        void Destroy() {        //manifestLoader.Unload(false);    }   }







0 0
原创粉丝点击