【小松教你手遊開發】【unity系統模塊開發】Unity5.5.2UI打包AssetBundle
剛好最近項目更新Unity5.5.2就順便由我來更新ui打包流程
這裏就把這次的經驗寫一下
這裏還是稍微解釋一下打包的基本目的:
打包ui就是把你做的界面打包出來成assetbundle包,講道理你就把每個界面打成bundle包在遊戲中你就可以直接加載來用,但是這樣子的話你的每個bundle包就會非常的大,為什麽呢,是因為這樣子每個界面的bundle包裏都包含這個界面用到的字體,貼圖atlas,texture,shader還可以有你自己使用的動態組件。
這樣子你的同一份資源都復制了很多份出來。
當然不能這樣子做
所以我們就需要把這些atlas,font給剝離開來獨立打包
不過新的打包方式讓我們不用再手動剝離開來這些東西,也就是沒有了剝離之後要重新引用的煩惱。
所要做的事就是把需要打包的東西改一改它的AssetBudnle名再一起build就好了
總的來說,就是把一個ui界面的下的atlas,font,texture,component記錄下來,
通過修改這個ui.prefab,atlas,font,texture,compoent的預制件的bundle名,最後調一下打包函數就可以了
(有的項目texutre和shader是有自己寫的管理類來加載,需要把引用置空的,這時候就需要實例ui.prefab,並把引用賦空,拷貝一份到另外一個文件夾中)
上一篇ui打包文章
http://blog.csdn.net/chrisfxs/article/details/55046339
而這次的流程是
1.清理數據,建立文件夾
2.遍歷所有文件夾下的ui界面prefab
3.遍歷所有prefab下的compoent(動態組件)
4.找出所有的資源(如atlas,font)用個list記錄下來
5.修改這些資源和這個ui.prefab的assetbundle名
6.build
補充一點!
遊戲加載assetbundle的時候要先加載atlas,font這些資源,最後加載ui資源
這樣才能保證引用沒有丟失
下面是代碼
//#if UNITY_5_MODE using UnityEngine; using UnityEditor; using System.Collections.Generic; using UnityEditor.SceneManagement; using UnityEngine.SceneManagement; using System.IO; public class BuildAssetbundle { public static string m_destFileName = "Assetbundle"; #if UNITY_ANDROID public static string PlatformExtension = ".android"; public static string Extension = ".x.android"; public static BuildTarget Target = BuildTarget.Android; public static string ASSETBUNDLE_PATH = Application.dataPath + "/../AndroidResources/StreamingAssets"; public static string FULL_ASSETBUNDLE_PATH = ASSETBUNDLE_PATH + "/" + m_destFileName; #elif UNITY_IOS public static string PlatformExtension = ".ios"; public static string Extension = ".x.ios"; public static BuildTarget Target = BuildTarget.iOS; public static string ASSETBUNDLE_PATH = Application.dataPath + "/../IosResources/StreamingAssets"; #endif #if BUILD_UI //需要打包的資源 public static List<UIFont> fontList = new List<UIFont>(); public static List<UIAtlas> atlasList = new List<UIAtlas>(); public static List<GameObject> componentList = new List<GameObject>(); public static List<GameObject> panelList = new List<GameObject>(); public static void BuildOnePanel() { ClearAllBundleName(); CleanTempData(); GameObject[] selectGameObjects = Selection.gameObjects; UnityEngine.Object selectFloder = Selection.activeObject; if (selectGameObjects != null && selectGameObjects.Length != 0) { foreach (GameObject selGb in selectGameObjects) { string selGbPath = AssetDatabase.GetAssetPath(selGb); if (selGbPath.StartsWith(BuildUtils.PANEL_ASSET_PATH)) { if (selGbPath.EndsWith(BuildUtils.PREFAB_SUFFIX)) { GameObject uiInstance = PrefabUtility.InstantiatePrefab(selGb) as GameObject; CheckComponent(uiInstance); FindRefrence(uiInstance.transform); string prefabPath = BuildUtils.TEMP_PANEL_PREFAB_PATH + "/" + uiInstance.name + BuildUtils.PREFAB_SUFFIX; PrefabUtility.CreatePrefab(prefabPath, uiInstance); GameObject prefabAsset = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject)) as GameObject; panelList.Add(prefabAsset); UnityEngine.Object.DestroyImmediate(uiInstance); } else { Debug.LogWarning("選擇的資源 " + selGb.name + " 不是界面Prefab!"); } } else { Debug.LogWarning("只能打包放在 " + BuildUtils.PANEL_ASSET_PATH + " 下面的界面Prefab"); } } StartBuildGameObjects(); BuildUtils.DeleteFileWithSuffixs(ASSETBUNDLE_PATH, new string[]{".manifest",""}, true, false); ShowBundleFolder(); EditorUtility.DisplayDialog("提示", "打包完成!", "確定"); } else { Debug.LogWarning("只能對 " + BuildUtils.PANEL_ASSET_PATH + " 下面的UI使用!"); } } public static void BuildAllPanel(bool hint) { ClearAllBundleName(); if (!hint || EditorUtility.DisplayDialog("提示", "確定打包 " + BuildUtils.PANEL_ASSET_PATH + " 下所有界面?", "確定", "取消")) { CleanTempData(); string[] files = Directory.GetFiles(BuildUtils.PANEL_ASSET_PATH); if (files.Length != 0) { foreach (string file in files) { if (file.EndsWith(BuildUtils.PREFAB_SUFFIX)) { GameObject uiInstance = PrefabUtility.InstantiatePrefab(AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(file)) as GameObject; string ui_panel_prefab_name = Path.GetFileNameWithoutExtension(file); CheckComponent(uiInstance); FindRefrence(uiInstance.transform); string prefabPath = BuildUtils.TEMP_PANEL_PREFAB_PATH + "/" + uiInstance.name + BuildUtils.PREFAB_SUFFIX; PrefabUtility.CreatePrefab(prefabPath, uiInstance); GameObject prefabAsset = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject)) as GameObject; panelList.Add(prefabAsset); UnityEngine.Object.DestroyImmediate(uiInstance); } } StartBuildGameObjects(); BuildUtils.DeleteFileWithSuffixs(ASSETBUNDLE_PATH, new string[]{".manifest",""}, true, false); } if (hint) { ShowBundleFolder(); EditorUtility.DisplayDialog("提示", BuildUtils.PANEL_ASSET_PATH + " 下的界面界面全部打包完成!", "確定"); } } } /// <summary> /// 對每一個要打包的Prefab保存組件信息,找出Atlas、Font等// /// </summary> /// <param name="com">COM.</param> static void FindRefrence(Transform com) { PrefabHierarchyInfo info = com.gameObject.AddComponent<PrefabHierarchyInfo>(); info.transforms = com.gameObject.GetComponentsInChildren<Transform>(true); info.myuianchors = com.gameObject.GetComponentsInChildren<MyUIAnchor>(true); UILabel[] uilabels = com.gameObject.GetComponentsInChildren<UILabel>(true); UISprite[] uisprites = com.gameObject.GetComponentsInChildren<UISprite>(true); UITexture[] uitextures = com.gameObject.GetComponentsInChildren<UITexture>(true); foreach (UILabel lab in uilabels) { UIFont font = lab.bitmapFont; if (font == null) { Debug.LogWarning(com.gameObject.name + " 下出現未使用UIFont或者沒有知道字體的UIlabel, " + lab.gameObject.name); continue; } string uifontPath = AssetDatabase.GetAssetPath(font); if (!uifontPath.StartsWith(BuildUtils.UIFONT_PREFAB_PATH)) Debug.LogWarning("使用了沒有放在" + BuildUtils.UIFONT_PREFAB_PATH + " 目錄下的UIFont:" + uifontPath); if (!fontList.Contains(font)) { fontList.Add(font); } lab.text = ""; } foreach (UISprite sp in uisprites) { UIAtlas atlas = sp.atlas; if (atlas == null) continue; string atlasPath = AssetDatabase.GetAssetPath(atlas); if (!atlasPath.StartsWith(BuildUtils.ATLAS_PREFAB_PATH)) Debug.LogWarning("使用了未放在" + BuildUtils.ATLAS_PREFAB_PATH + "目錄下的Atlas:" + atlasPath); sp.RecordAtlasName = atlas.name; if (!atlasList.Contains(atlas)) atlasList.Add(atlas); } foreach (UITexture t in uitextures) { t.mainTexture = null; t.shader = null; } com.parent = null; } /// <summary> /// 對找出的需要打包資源打包// /// </summary> private static void StartBuildGameObjects() { EditorUtility.UnloadUnusedAssetsImmediate(); AssetbundleCommonFun.SetAssetBundlesName<UIFont>(fontList, Extension, false); AssetbundleCommonFun.SetAssetBundlesName<UIAtlas>(atlasList, Extension, false); AssetbundleCommonFun.SetAssetBundlesName<GameObject>(componentList, Extension, false); AssetbundleCommonFun.SetAssetBundlesName<GameObject>(panelList, Extension, false); AssetDatabase.Refresh(); BuildAll(); CleanTempData(); ClearAllBundleName(); } //在一次打包過程中,出現過的Component,檢測多個Panel裏面的(DynamicComponent)重名// static List<string> componentNames = new List<string>(); //支持無限深度的Component嵌套 static void CheckComponent(GameObject go) { string prefabPath = ""; Dictionary<uint, List<Transform>> allComponent = new Dictionary<uint, List<Transform>>(); FindComponents(go.transform, 0, ref allComponent); uint[] indexs = new uint[allComponent.Keys.Count]; allComponent.Keys.CopyTo(indexs, 0); System.Array.Sort(indexs); for (int i = indexs.Length - 1; i >= 0; i--) { foreach (Transform com in allComponent[indexs[i]]) { FindRefrence(com); prefabPath = BuildUtils.TEMP_COMPONENT_PREFAB_PATH + "/" + com.name + BuildUtils.PREFAB_SUFFIX; PrefabUtility.CreatePrefab(prefabPath, com.gameObject); GameObject prefabAsset = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject)) as GameObject; componentList.Add(prefabAsset); } } for (int i = indexs.Length - 1; i >= 0; i--) { foreach (Transform com in allComponent[indexs[i]]) { UnityEngine.Object.DestroyImmediate(com.gameObject); } } } /// <summary> /// 遞歸尋找動態組件// /// </summary> /// <param name="tf">Tf.</param> /// <param name="index">Index.</param> /// <param name="dict">Dict.</param> static void FindComponents(Transform tf, uint index, ref Dictionary<uint, List<Transform>> dict) { if (tf.name.Contains("(DynamicComponent)")) { foreach (Transform sonTf in tf) { if (componentNames.Contains(sonTf.name)) { UnityEngine.Debug.LogError(tf.name + " 子物體中出現同名的動態組件 " + sonTf.name); UnityEngine.Object.DestroyImmediate(sonTf); continue; } if (!sonTf.name.Contains("(DynamicComponent)")) { componentNames.Add(sonTf.name); if (!dict.ContainsKey(index)) dict.Add(index, new List<Transform>()); dict[index].Add(sonTf); if (sonTf.childCount > 0) FindComponents(sonTf, index + 1, ref dict); } else { if (sonTf.childCount > 0) FindComponents(sonTf, index + 1, ref dict); } } } else { foreach (Transform sonTf in tf) { if (sonTf.childCount > 0) FindComponents(sonTf, index + 1, ref dict); } } } static void CleanTempData() { fontList.Clear(); atlasList.Clear(); componentList.Clear(); componentNames.Clear(); } #endif #region tools static void BuildAll() { EditorUtility.ClearProgressBar(); AssetbundleCommonFun.CreatePath(ASSETBUNDLE_PATH + "/Assetbundle"); BuildPipeline.BuildAssetBundles(ASSETBUNDLE_PATH + "/Assetbundle", BuildAssetBundleOptions.ChunkBasedCompression, Target); } //[MenuItem("[AssetBundles]/Build Bundles Independent")] static void BuildBundlesIndependent() { List<Object> list = new List<Object>(); list.AddRange(Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets)); int count = list.Count; string temp_path; List<string> pathList = new List<string>(); foreach (Object o in list) { if (o == null) { continue; } AssetbundleCommonFun.ChangeTextureFormat(o); temp_path = AssetDatabase.GetAssetPath(o); if (!pathList.Contains(temp_path)) { pathList.Add(temp_path); } } BuildIndependent(pathList); } static void BuildIndependent(List<string> pathList) { string OutPutFolder = ASSETBUNDLE_PATH + "/Assetbundle"; AssetbundleCommonFun.CreatePath(OutPutFolder); AssetBundleBuild temp_build; List<AssetBundleBuild> abbs = new List<AssetBundleBuild>(); int count = pathList.Count; int index = 0; foreach (string item in pathList) { if (item == null) { index++; continue; } EditorUtility.DisplayProgressBar("Build Bundles Independent", item, (float)index / (float)count); if (!string.IsNullOrEmpty(item)) { temp_build = new AssetBundleBuild(); temp_build.assetBundleName = AssetbundleCommonFun.GetBundleName(item, Extension); temp_build.assetNames = new string[] { item }; abbs.Add(temp_build); } index++; } BuildPipeline.BuildAssetBundles(OutPutFolder, abbs.ToArray(), BuildAssetBundleOptions.ChunkBasedCompression, Target); string mainConfigPath = OutPutFolder + "/" + Path.GetFileName(OutPutFolder); if (File.Exists(mainConfigPath)) { File.Delete(mainConfigPath); } AssetbundleCommonFun.ExportModifyFilesInfo(ASSETBUNDLE_PATH + "/Assetbundle"); EditorUtility.ClearProgressBar(); EditorUtility.DisplayDialog("提示", "操作結束", "OK"); } //[@MenuItem("[AssetBundles]/Set Name for self")] 此功能不開放 static void SetNameForSelf() { List<Object> list = new List<Object>(); list.AddRange(Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets)); int count = list.Count; int index = 0; foreach (Object o in list) { if (o == null) { index++; continue; } string path = AssetDatabase.GetAssetPath(o); AssetbundleCommonFun.SetBundleName(path, Extension); index++; EditorUtility.DisplayProgressBar("Set Assetbundle Name", path, (float)index / (float)count); } EditorUtility.ClearProgressBar(); EditorUtility.DisplayDialog("提示", "操作結束", "OK"); } //[@MenuItem("[AssetBundles]/Set Assetbundle Name")] 此功能不開放 static void SetName() { List<Object> list = new List<Object>(); list.AddRange(Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets)); int count = list.Count; int index = 0; foreach (Object o in list) { if (o == null) { index++; continue; } string path = AssetDatabase.GetAssetPath(o); AssetbundleCommonFun.SetBundleName(path, Extension); index++; EditorUtility.DisplayProgressBar("Set Assetbundle Name", path, (float)index / (float)count); } EditorUtility.ClearProgressBar(); //EditorUtility.DisplayDialog("提示", "操作結束", "OK"); } //[@MenuItem("[AssetBundles]/Clear Selected AssetbundleName")] static void ClearName() { List<Object> list = new List<Object>(); list.AddRange(Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets)); int count = list.Count; int index = 0; foreach (Object o in list) { if (o == null) { index++; continue; } string path = AssetDatabase.GetAssetPath(o); AssetbundleCommonFun.SetBundleName(path, "", true); //AssetbundleCommonFun.SetDependenciesName(path, "", false, true); index++; EditorUtility.DisplayProgressBar("Clear Assetbundle Name", path, (float)index / (float)count); } EditorUtility.ClearProgressBar(); //EditorUtility.DisplayDialog("提示", "操作結束", "OK"); } //[@MenuItem("[AssetBundles]/Clear All AssetbundleNames")] static void ClearAllBundleName() { string[] allBundleNames = AssetDatabase.GetAllAssetBundleNames(); List<string> hasBundleNameAssets = new List<string>(); foreach (string n in allBundleNames) { foreach (string p in AssetDatabase.GetAssetPathsFromAssetBundle(n)) { hasBundleNameAssets.Add(p); } } float idx = 0f; foreach (string asset in hasBundleNameAssets) { AssetbundleCommonFun.SetBundleName(asset, "", true); EditorUtility.DisplayProgressBar("清除所有Bundle名稱", "當前處理文件:" + Path.GetFileName(asset), idx++ / hasBundleNameAssets.Count); } EditorUtility.ClearProgressBar(); AssetDatabase.RemoveUnusedAssetBundleNames(); AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate); //EditorUtility.DisplayDialog("提示", "操作結束", "OK"); } /// <summary> /// 顯示Bundle文件夾// /// </summary> static void ShowBundleFolder() { string path = FULL_ASSETBUNDLE_PATH +"/assets"; path = path.Replace("/", "\\"); Debug.Log(path); System.Diagnostics.Process.Start("explorer.exe", "/select," + path); } #endregion } //#endif
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
using System.Text;
public class AssetbundleCommonFun
{
#if UNITY_ANDROID
private static string strLocalFileName = "Android_LocalFilesInfo.asset";
#elif UNITY_IOS
private static string strLocalFileName = "Ios_LocalFilesInfo.asset";
#endif
private static List<string> componentList = new List<string>();
static AssetImporter m_importer = null;
public static void ClearAllBundleName()
{
string[] allBundleNames = AssetDatabase.GetAllAssetBundleNames();
List<string> hasBundleNameAssets = new List<string>();
foreach (string n in allBundleNames)
{
foreach (string p in AssetDatabase.GetAssetPathsFromAssetBundle(n))
{
hasBundleNameAssets.Add(p);
}
}
float idx = 0f;
foreach (string asset in hasBundleNameAssets)
{
SetBundleName(asset, "", false);
EditorUtility.DisplayProgressBar("清除所有Bundle名稱", "當前處理文件:" + Path.GetFileName(asset), idx++ / hasBundleNameAssets.Count);
}
EditorUtility.ClearProgressBar();
AssetDatabase.RemoveUnusedAssetBundleNames();
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
}
public static void CreatePath(string path)
{
string NewPath = path.Replace("\\", "/");
string[] strs = NewPath.Split(‘/‘);
string p = "";
for (int i = 0; i < strs.Length; ++i)
{
p += strs[i];
if (i != strs.Length - 1)
{
p += "/";
}
if (!Path.HasExtension(p))
{
if (!Directory.Exists(p))
Directory.CreateDirectory(p);
}
}
}
public static string SetBundleName(string path, string name, bool isForce = false)
{
if (!isForce)
{
if (Directory.Exists(path))
{
return null;
}
}
string dictName = Path.GetDirectoryName(path);
string fileName = Path.GetFileNameWithoutExtension(path);
string extension = Path.GetExtension(path);
dictName = dictName.Replace("UIResources_temp", "UIResources");
if (!isForce)
{
if (extension.Equals(".dll") || extension.Equals(".cs") || extension.Equals(".js") || (name != "" && fileName.Contains("atlas") && !extension.Equals(".prefab")))
{
return null;
}
}
m_importer = AssetImporter.GetAtPath(path);
if (name != "")
{
m_importer.assetBundleName = dictName + "/" + fileName + name;
}
else
{
m_importer.assetBundleName = "";
}
AssetDatabase.Refresh();
return m_importer.assetBundleName;
}
public static string GetBundleName(string path, string name, bool isForce = false)
{
string retBundleName = null;
if (!isForce)
{
if (Directory.Exists(path))
{
return retBundleName;
}
}
string dictName = Path.GetDirectoryName(path);
string fileName = Path.GetFileNameWithoutExtension(path);
string extension = Path.GetExtension(path);
if (!isForce)
{
if (extension.Equals(".dll") || extension.Equals(".cs") || extension.Equals(".js") || (name != "" && fileName.Contains("atlas") && !extension.Equals(".prefab")))
{
return null;
}
}
if (name != "")
{
retBundleName = dictName + "/" + fileName + name;
//Object tex = AssetDatabase.LoadAssetAtPath(path, typeof(Object));
//if (tex is Texture2D)
//{
// SetTexture(tex as Texture2D);
//}
}
Debug.Log("Asset name: " + fileName);
AssetDatabase.Refresh();
return retBundleName;
}
static void FindComponents(Transform tf, uint index, ref Dictionary<uint, List<Transform>> dict)
{
if (tf.name.Contains("(DynamicComponent)"))
{
foreach (Transform sonTf in tf)
{
if (componentList.Contains(sonTf.name))
{
Debug.LogWarning("same name component...");
UnityEngine.Object.DestroyImmediate(sonTf);
continue;
}
if (!sonTf.name.Contains("(DynamicComponent)"))
{
Debug.Log("找到組件" + sonTf.name + "深度" + index);
componentList.Add(sonTf.name);
if (!dict.ContainsKey(index))
dict.Add(index, new List<Transform>());
dict[index].Add(sonTf);
if (sonTf.childCount > 0)
FindComponents(sonTf, index + 1, ref dict);
}
else
{
if (sonTf.childCount > 0)
FindComponents(sonTf, index + 1, ref dict);
}
}
}
else
{
foreach (Transform sonTf in tf)
{
if (sonTf.childCount > 0)
FindComponents(sonTf, index + 1, ref dict);
}
}
}
public static void SetTexture(Texture2D tex)
{
string path = AssetDatabase.GetAssetPath(tex);
TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
if (importer != null)
{
if (!(importer.textureType == TextureImporterType.NormalMap || importer.normalmap))
importer.mipmapEnabled = false;
importer.npotScale = TextureImporterNPOTScale.ToNearest;
importer.textureType = TextureImporterType.Default;
importer.spriteImportMode = SpriteImportMode.None;
importer.isReadable = false;
if (path.Contains("_alpha8"))
{
importer.textureFormat = TextureImporterFormat.Alpha8;
}
else
{
importer.textureFormat = SetTextureFormat(tex, importer);
}
importer.maxTextureSize = 8192;
AssetDatabase.ImportAsset(path);
}
}
static TextureImporterFormat SetTextureFormat(Texture t, TextureImporter importer)
{
TextureImporterFormat TextureFormat;
#if UNITY_IPHONE
if (fun(t.width) && fun(t.height))
{
if (importer.DoesSourceTextureHaveAlpha())
{
TextureFormat = TextureImporterFormat.PVRTC_RGBA4;
}
else
{
TextureFormat = TextureImporterFormat.PVRTC_RGB4;
}
}
else
{
TextureFormat = TextureImporterFormat.ETC2_RGBA8;
}
#elif UNITY_ANDROID
if (fun(t.width) && fun(t.height))
{
if (importer.DoesSourceTextureHaveAlpha())
{
//importer.alphaIsTransparency = true;
TextureFormat = TextureImporterFormat.ETC2_RGBA8;
}
else
TextureFormat = TextureImporterFormat.ETC_RGB4;
}
else {
if (importer.DoesSourceTextureHaveAlpha())
{
//importer.alphaIsTransparency = true;
TextureFormat = TextureImporterFormat.RGBA16;
}
else
TextureFormat = TextureImporterFormat.RGB16;
Debug.LogWarning("Texture " + t.name + " 尺寸不為2的冪次方,無法使用ETC壓縮,當前使用 " + TextureFormat.ToString());
}
#else
TextureFormat = TextureImporterFormat.RGBA32;
#endif
return TextureFormat;
}
static bool fun(int v)
{
bool flag = false;
if ((v > 0) && (v & (v - 1)) == 0)
flag = true;
return flag;
}
public static void ExportModifyFilesInfo(string path)
{
string extension = "";
string[] retFils = Directory.GetFiles(path, "*.manifest", SearchOption.AllDirectories);
//LocalFilesInfo filesInfo = ScriptableObject.CreateInstance<LocalFilesInfo>();
foreach (var item in retFils)
{
File.Delete(item);
}
}
private static void FileCopy(string sourceFileName, string destFileName)
{
string dictName = Path.GetDirectoryName(destFileName);
CreatePath(dictName);
File.Copy(sourceFileName, destFileName);
}
private static string GetMD5HashFromFile(string fileName)
{
try
{
FileStream file = new FileStream(fileName, FileMode.Open);
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] retVal = md5.ComputeHash(file);
file.Close();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < retVal.Length; i++)
{
sb.Append(retVal[i].ToString("x2"));
}
return sb.ToString();
}
catch (System.Exception ex)
{
throw new System.Exception("GetMD5HashFromFile() fail, error:" + ex.Message);
}
}
public static void ChangeTextureFormat(Object obj)
{
Object[] dependObjects;
dependObjects = EditorUtility.CollectDependencies(new Object[] { obj });
foreach (Object val in dependObjects)
{
if (val is Texture2D)
{
SetTexture(val as Texture2D);
}
}
AssetDatabase.Refresh();
}
public static void SetAssetBundlesName<T>(List<T> list, string Extension, bool needRefresh) where T : Object
{
for (int i = 0; i < list.Count; i++)
{
SetAssetBundleName(list[i], Extension, needRefresh);
}
}
public static void SetAssetBundleName<T>(T asset, string Extension, bool needRefresh) where T : Object
{
string path = AssetDatabase.GetAssetPath(asset);
SetBundleName(path, Extension, needRefresh);
}
}
【小松教你手遊開發】【unity系統模塊開發】Unity5.5.2UI打包AssetBundle