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文件,那么在加载使用一个资源的时候,就要根据这个文件,先去加载这个资源依赖的所有资源,然后再加载这个资源,然后就可以使用啦。加载这块,下次再整理。
代码都在这了,工程我就不上传了。
拜了个拜!
- 本文固定链接: http://www.shihuanjue.com/?p=57
- 转载请注明: 乔 2015年08月10日 于 是幻觉 发表