Unity5.x版本AssetBundle打包研究

Unity5的AssetBundle打包机制和以前版本不太一样。简单的说就是,只要给你要打包的资源设置一个AssetBundleName ,Unity自身会对这些设置了名字的资源进行打包,如果一个资源依赖了另一个资源。Unity自己会处理依赖关 系,AssetBundleManifest文件就保存着这些资源的依赖关系。
比如一个UI面板.Prefab,依赖了一个图集Atlas,一个字体文件
做个测试:
只给UI面板3.prefab设置AssetBundleName。

打出包来看,别看只有371KB,那是因为我拿得面板不是很复杂,依赖的图集,字体,本身就不是很大。
要是项目中的话,你不处理依赖打包的话,几M都是有的。

要是有其它的UI面板,设置AssetBundleName,打出包,都是这么大的

依赖文件显示资源没依赖,这是因为每一个面板里面都单独打包了一份图集资源,字体资源。显然这是不可取的。
对于同类型的UI面板来说,这些图集和字体文件,大家用的都是同一份,只要打包出一份,大家共享就好了。
接下给图集资源,字体文件都设置AssetBundleName,再进行打包,可以看到变小了。

在看.manifest文件,有了依赖关系。

项目中,资源辣么多,总不能在编辑器里一个一个给资源进行设置AssetBundleName吧,那会蛋疼死的,是吧。
上代码

using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;
 
/// <summary>
/// 把Resource下的资源打包成.unity3d 到StreamingAssets目录下
/// </summary>
public class Builder : Editor
{
    public static string sourcePath = Application.dataPath + "/Resources";
    const string AssetBundlesOutputPath = "Assets/StreamingAssets";
 
    [MenuItem("Tools/AssetBundle/Build")]
    public static void BuildAssetBundle()
    {
        ClearAssetBundlesName ();
 
        Pack (sourcePath);
 
        string outputPath = Path.Combine (AssetBundlesOutputPath,Platform.GetPlatformFolder(EditorUserBuildSettings.activeBuildTarget));
        if (!Directory.Exists (outputPath))
        {
            Directory.CreateDirectory(outputPath);
        }
 
        //根据BuildSetting里面所激活的平台进行打包
        BuildPipeline.BuildAssetBundles (outputPath,0,EditorUserBuildSettings.activeBuildTarget);
 
        AssetDatabase.Refresh ();
 
        Debug.Log ("打包完成");
 
    }
 
    /// <summary>
    /// 清除之前设置过的AssetBundleName,避免产生不必要的资源也打包
    /// 之前说过,只要设置了AssetBundleName的,都会进行打包,不论在什么目录下
    /// </summary>
    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)
    {
        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"))
                {
                    file (files[i].FullName);
                }
            }
        }
    }
 
    static void file(string 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 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;
        }
    }
}

有了这个包含所有资源的依赖关系的.manifest文件,那么在加载使用一个资源的时候,就要根据这个文件,先去加载这个资源依赖的所有资源,然后再加载这个资源,然后就可以使用啦。加载这块,下次再整理。
代码都在这了,工程我就不上传了。
拜了个拜!

posted @ 2016-05-13 11:26  Joe师傅  阅读(1355)  评论(0编辑  收藏  举报