zoukankan      html  css  js  c++  java
  • 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文件,那么在加载使用一个资源的时候,就要根据这个文件,先去加载这个资源依赖的所有资源,然后再加载这个资源,然后就可以使用啦。加载这块,下次再整理。
    代码都在这了,工程我就不上传了。
    拜了个拜!

  • 相关阅读:
    使用注解方式实现 AOP和IoC
    代理工厂生成器和顾问包装通知
    多种方式实现AOP
    Spring面试题
    使用集合方式注入IoC
    Spring代理模式
    Spring AOP的使用及案例
    bzoj 1715: [Usaco2006 Dec]Wormholes 虫洞 -- spfa判断负环
    bzoj 1654: [Usaco2006 Jan]The Cow Prom 奶牛舞会 -- Tarjan
    bzoj 1651: [Usaco2006 Feb]Stall Reservations 专用牛棚 -- 线段树
  • 原文地址:https://www.cnblogs.com/joeshifu/p/5488762.html
Copyright © 2011-2022 走看看