Unity5 新AssetBundle打包方式 BuildPipeline.BuildAssetBundles

         Unity5增加了新的打包AssetBundle方式-> BuildPipeline.BuildAssetBundles,大体思想是把资源以及依赖项分别打包,并用文本记录它们间的依赖关系,这种方式相对旧版本将资源粗暴的打成一个包来说,带来的好处也显而易见,每个资源以及依赖项都只打包一次不会造成依赖循环(不了解的同学可以看一下Unity AssetBundle爬坑手记 - 夜阑卧听风吹雨),但同时打包后的资源更碎片化,导致加载耗时更多。大家都有复制文件的经验,复制一个包比复制一堆碎文件快(同大小的两份文件)同样道理。

        思想上有点类似李总(李剑英)的资源热更新方案,将资源信息(布局,参数等)解析成文本,使用的时候只需下载文本文件(占用物理内存小),再根据文本文件生成资源。但据我测试,BuildPipeline.BuildAssetBundles执行效率较低,在加载相同prefab的前提下根据文本生成prefab耗时51.59ms,使用BuildPipeline.BuildAssetBundles 加载耗时约118ms。这里只给大家一个大概的参考。


       1.  打包AssetBundle,代码来源http://blog.csdn.net/onafioo/article/details/50969945, 稍作修改增加了自动关联依赖项的方法

using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;

/// 
/// 把Resource下的资源打包成.data到OutPut目录下
/// 
public class Builder : Editor
{
    public static string sourcePath = Application.dataPath + "/Resource";
    const string AssetBundlesOutputPath = "Assets/OutPut";

    [MenuItem("Custom/BuildAssetBundle")]
    public static void BuildAssetBundle()
    {
        ClearAssetBundlesName();

        Pack(sourcePath);

        string outputPath = Path.Combine(AssetBundlesOutputPath, Platform.GetPlatformFolder(EditorUserBuildSettings.activeBuildTarget));
        if (!Directory.Exists(outputPath))
        {
            Directory.CreateDirectory(outputPath);
        }

        //根据BuildSetting里面所激活的平台进行打包 设置过AssetBundleName的都会进行打包
        BuildPipeline.BuildAssetBundles(outputPath, 0, EditorUserBuildSettings.activeBuildTarget);

        AssetDatabase.Refresh();

        Debug.Log("打包完成");

    }

    /// 
    /// 清除之前设置过的AssetBundleName,避免产生不必要的资源也打包
    /// 之前说过,只要设置了AssetBundleName的,都会进行打包,不论在什么目录下
    /// 
    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);
        }
        length = AssetDatabase.GetAllAssetBundleNames().Length;
        Debug.Log(length);
    }

    static void Pack(string source)
    {
        //Debug.Log("Pack source " + source);
        DirectoryInfo folder = new DirectoryInfo(source);
        FileSystemInfo[] files = folder.GetFileSystemInfos();
        int length = files.Length;
        for (int i = 0; i < length; i++)
        {
            if (files[i] is DirectoryInfo)
            {
                Pack(files[i].FullName);
            }
            else
            {
                if (!files[i].Name.EndsWith(".meta"))
                {
                    fileWithDepends(files[i].FullName);
                }
            }
        }
    }
    //设置要打包的文件
    static void fileWithDepends(string source)
    {
        Debug.Log("file source " + source);
        string _source = Replace(source);
        string _assetPath = "Assets" + _source.Substring(Application.dataPath.Length);

        Debug.Log(_assetPath);

        //自动获取依赖项并给其资源设置AssetBundleName
        string[] dps = AssetDatabase.GetDependencies(_assetPath);
        foreach (var dp in dps)
        {
            Debug.Log("dp " + dp);
            if (dp.EndsWith(".cs"))
                continue;
            AssetImporter assetImporter = AssetImporter.GetAtPath(dp);
            string pathTmp = dp.Substring("Assets".Length + 1);
            string assetName = pathTmp.Substring(pathTmp.IndexOf("/") + 1);
            assetName = assetName.Replace(Path.GetExtension(assetName), ".data");
            Debug.Log(assetName);
            assetImporter.assetBundleName = assetName;
        }

    }

    //设置要打包的文件
    static void file(string source)
    {
        Debug.Log("file source " + source);
        string _source = Replace(source);
        string _assetPath = "Assets" + _source.Substring(Application.dataPath.Length);
        string _assetPath2 = _source.Substring(Application.dataPath.Length + 1);
        //Debug.Log (_assetPath);

        //在代码中给资源设置AssetBundleName
        AssetImporter assetImporter = AssetImporter.GetAtPath(_assetPath);
        string[] dps = AssetDatabase.GetDependencies(_assetPath);
        foreach (var dp in dps)
        {
            Debug.Log("dp " + dp);
        }
        string assetName = _assetPath2.Substring(_assetPath2.IndexOf("/") + 1);
        assetName = assetName.Replace(Path.GetExtension(assetName), ".unity3d");
        Debug.Log(assetName);
        assetImporter.assetBundleName = assetName;
    }

    static string Replace(string s)
    {
        return s.Replace("\\", "/");
    }
}

public class Platform
{
    public static string GetPlatformFolder(BuildTarget target)
    {
        switch (target)
        {
            case BuildTarget.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;
        }
    }
}

2.加载AssetBundle

using UnityEngine;
using System.Collections;
using System;

public class TestLoadNewAB : MonoBehaviour
{

    void OnGUI()
    {
        if (GUILayout.Button("LoadAssetbundle"))
        {
            DateTime t0 = DateTime.Now;
            //首先加载Manifest文件;
            AssetBundle manifestBundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath
                                                                  + "/Android/Android");

            Debug.Log(manifestBundle == null);
            if (manifestBundle != null)
            {
                AssetBundleManifest manifest = (AssetBundleManifest)manifestBundle.LoadAsset("AssetBundleManifest");
                Debug.Log(manifest == null);
                //获取依赖文件列表;
                string[] cubedepends = manifest.GetAllDependencies("cube.data");

                Debug.Log(cubedepends.Length);
                foreach (var item in cubedepends)
                {
                    Debug.Log("depends " + item);
                }
                AssetBundle[] dependsAssetbundle = new AssetBundle[cubedepends.Length];

                for (int index = 0; index < cubedepends.Length; index++)
                {
                    //加载所有的依赖文件;
                    dependsAssetbundle[index] = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/Android/" + cubedepends[index]);

                }
                DateTime t1 = DateTime.Now;

                //加载我们需要的文件;"
                AssetBundle cubeBundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/Android/cube.data");
                Debug.Log(cubeBundle == null);
                GameObject cube = cubeBundle.LoadAsset("cube") as GameObject;
                Debug.Log(cube == null);
                if (cube != null)
                {
                    Instantiate(cube);
                  

                    DateTime t2 = DateTime.Now;

                    Debug.Log("LoadView Time1:" + (t1 - t0).TotalMilliseconds + " Time2:" + (t2 - t1).TotalMilliseconds);//+ " Time3:" + (t3 - t2).TotalMilliseconds
                }
            }


        }
    }
}



你可能感兴趣的:(unityCode)