实例介绍
【实例截图】
【核心代码】
using System.Collections.Generic; using UnityEngine; using UnityEditor; using System.IO; using System.Linq; public class AssetbundlePackat { //把需要热更的Resources资源放入HotUpdate文件夹,如果需要默认读取resources/HotUpdate下的资源 //,请不要添加到LevelVersion.xml版本中,也不要生成ab包,等需要热更修改内容时,再包含进去版本中,并生成ab包 //注意:不要为了省时间,只打一个需要的ab包,需要整体重新打ab包,因为会生成ab依赖分析包 static string m_beginPath; static string beginPath { get { if (string.IsNullOrEmpty(m_beginPath)) { int index = Application.dataPath.LastIndexOf("Assets"); m_beginPath = Application.dataPath.Remove(index); } return m_beginPath; } } #region 清除AssetBundle包名 [MenuItem("HotTools/ClearAbName")] static void ClearABNames() { //清除旧的ab包名 EditorUtility.DisplayProgressBar("搜索ab包名", "进行中...", 0.2f); string[] abnames = AssetDatabase.GetAllAssetBundleNames(); for(int i=0;i<abnames.Length;i ) { EditorUtility.DisplayProgressBar("清除ab包名", abnames[i], (i 1f) / abnames.Length); AssetDatabase.RemoveAssetBundleName(abnames[i], true); } EditorUtility.ClearProgressBar(); } #endregion #region 设置AssetBundle包名 const int ReferenceThreshold = 2;//大于阀值设置ab名字,不被包含,而被依赖 static int objDependencieCount = 0;//依赖计数 static Dictionary<string, bool> dicAtlasSetAbNameFlag = new Dictionary<string,bool>();//图集设置assetName标识 static Dictionary<string, Dictionary<string,bool>> dicObjRelyNum = new Dictionary<string, Dictionary<string,bool>>();//key=objPath value=依赖列表 static Dictionary<string, Dictionary<string,bool>> dicAtlasObjRelyNum = new Dictionary<string, Dictionary<string,bool>>();//key=packing Tag value=依赖列表 static void InitSetAssetBundle() { AssetDatabase.SaveAssets(); objDependencieCount = 0; dicAtlasSetAbNameFlag.Clear(); dicObjRelyNum.Clear(); dicAtlasObjRelyNum.Clear(); dicSpritePackingTagList.Clear(); GetSpriteListAtPackingTag(Application.dataPath); } #region packing Tag sprite列表 static Dictionary<string, List<string>> dicSpritePackingTagList = new Dictionary<string, List<string>>();//packing Tag sprite列表 static void GetSpriteListAtPackingTag(string path) { string[] filePaths = Directory.GetFiles(path); List<string> ignoreExtens = new List<string> { "", ".lua", ".cs", ".dll", ".json", ".mat", ".meta", ".DS_Store", ".text", ".xml", ".prefab", ".ab", ".mp4", ".mp3" }; for (int i=0;i<filePaths.Length;i ) { string fp = filePaths[i]; string exten = Path.GetExtension(fp); if (ignoreExtens.Contains(exten)) continue; string relativePath = fp.Replace(Application.dataPath, "Assets"); EditorUtility.DisplayProgressBar("分析图集Sprite", relativePath, ((float)i) / filePaths.Length); AssetImporter aImport = AssetImporter.GetAtPath(relativePath); TextureImporter ti = aImport as TextureImporter; if (ti != null && ti.textureType == TextureImporterType.Sprite) { ti.isReadable = false; if (!dicSpritePackingTagList.ContainsKey(ti.spritePackingTag)) dicSpritePackingTagList.Add(ti.spritePackingTag, new List<string>()); dicSpritePackingTagList[ti.spritePackingTag].Add(relativePath); } } string[] direPaths = Directory.GetDirectories(path); foreach (var d in direPaths) { if (Path.GetDirectoryName(d) == "Editor") continue; GetSpriteListAtPackingTag(d); } } #endregion /// <summary> /// 热更新目录 /// </summary> const string ScenesDirector = "/Scenes"; /// <summary> /// 分析依赖 /// </summary> static void AnalyzeRely() { InitSetAssetBundle(); DirectoryInfo dirinfo=null; #region Resources文件夹下资源对象 string resourceHotDire = string.Format("{0}/Resources/{1}", Application.dataPath, HotDataContext.HotDirector); //现在Resources文件夹找需要打ab的资源 if (Directory.Exists(resourceHotDire)) dirinfo = new DirectoryInfo(resourceHotDire); else if (Directory.Exists(string.Format("{0}/{1}", Application.dataPath, HotDataContext.HotDirector))) dirinfo = new DirectoryInfo(string.Format("{0}/{1}",Application.dataPath, HotDataContext.HotDirector)); if (dirinfo != null) { FileInfo[] fs = dirinfo.GetFiles("*.*", SearchOption.AllDirectories); foreach (FileInfo f in fs) { string ext_name = Path.GetExtension(f.Name); if (ext_name == ".meta" || ext_name == ".DS_Store") continue; string path = f.FullName.Replace("\\", "/"); string relativalPath = path.Replace(Application.dataPath, "Assets"); ObjDependencie(string.Empty, relativalPath); } } #endregion #region Scenes文件 EditorBuildSettingsScene[] scenes = EditorBuildSettings.scenes; if (Directory.Exists(Application.dataPath ScenesDirector)) { dirinfo = new DirectoryInfo(Application.dataPath ScenesDirector); FileInfo[] fs = dirinfo.GetFiles("*.unity", SearchOption.TopDirectoryOnly); foreach (FileInfo f in fs) { string path = f.FullName.Replace("\\", "/"); string relativalPath = path.Replace(Application.dataPath, "Assets"); for (int i = 0; i < scenes.Length; i ) { EditorBuildSettingsScene scene = scenes[i]; if (scene.path.Equals(relativalPath)) ObjDependencie(string.Empty, relativalPath); } } } #endregion } [MenuItem("HotTools/SetAbName")] static void SetAssetBundleName() { //把图集建立启用Editor->Project Settings->Editor->Sprote Packer Mode Enabled //清除旧的ab包名 //ClearABNames(); AnalyzeRely();//分析依赖 SetAbName(); } static void SetAbName() { int curProgress = 0; float totalProgress = dicObjRelyNum.Count dicAtlasObjRelyNum.Count; foreach (string objPath in dicObjRelyNum.Keys) { EditorUtility.DisplayProgressBar("设置ab包名", objPath, curProgress / totalProgress); if (!dicObjRelyNum[objPath].ContainsKey(string.Empty) && dicObjRelyNum[objPath].Count < ReferenceThreshold) continue; string exten = Path.GetExtension(objPath); string newExten = exten.Replace('.', '_'); string assetbundleName = objPath.Replace(exten, newExten); assetbundleName = assetbundleName.Replace('/', '.'); AssetImporter aImport = AssetImporter.GetAtPath(objPath); aImport.SetAssetBundleNameAndVariant(assetbundleName ".ab", string.Empty); } //图集 foreach (string packingTag in dicAtlasObjRelyNum.Keys) { EditorUtility.DisplayProgressBar("设置ab包名", packingTag, curProgress / totalProgress); if (dicAtlasObjRelyNum[packingTag].Count < ReferenceThreshold) continue; //if (dicAtlasObjRelyNum[packingTag] < Threshold) continue; List<string> list = dicSpritePackingTagList[packingTag]; for (int i = 0; i < list.Count; i ) { AssetImporter tempImport = AssetImporter.GetAtPath(list[i]); tempImport.SetAssetBundleNameAndVariant(packingTag "_atlas" ".ab", string.Empty);// 图集格式:atlas } } EditorUtility.ClearProgressBar(); AssetDatabase.SaveAssets(); } static void ObjDependencie(string referenceObjPath,string objPath) { EditorUtility.DisplayProgressBar("正在分析依赖" objDependencieCount , objPath, 0); AssetImporter aImport= AssetImporter.GetAtPath(objPath); TextureImporter ti = aImport as TextureImporter; if (ti != null && ti.textureType == TextureImporterType.Sprite) { if (!dicAtlasSetAbNameFlag.ContainsKey(ti.spritePackingTag)) { dicAtlasSetAbNameFlag.Add(ti.spritePackingTag, true); dicAtlasObjRelyNum.Add(ti.spritePackingTag, new Dictionary<string, bool>()); } if(!dicAtlasObjRelyNum[ti.spritePackingTag].ContainsKey(referenceObjPath))dicAtlasObjRelyNum[ti.spritePackingTag].Add(referenceObjPath,true); return; } if (!dicObjRelyNum.ContainsKey(objPath)) dicObjRelyNum.Add(objPath, new Dictionary<string, bool>()); if(!dicObjRelyNum[objPath].ContainsKey(referenceObjPath)) dicObjRelyNum[objPath].Add(referenceObjPath, true); string[] relyPathArr = AssetDatabase.GetDependencies(objPath, false); foreach (string relyObjPath in relyPathArr) { if (objPath == relyObjPath) continue;//原对象本身,不依赖自己 string exten = Path.GetExtension(relyObjPath); if (exten == ".cs") continue; if (exten == ".dll") continue; ObjDependencie(objPath,relyObjPath); } } #endregion [MenuItem("HotTools/所选物体设置AbName")] static void SelectObjectSetAbName() { ClearABNames(); InitSetAssetBundle(); List<string> relativalPathList = new List<string>(); EditorBuildSettingsScene[] scenes = EditorBuildSettings.scenes; Object[] objs= Selection.objects; foreach (var obj in objs) { string relativalPath= AssetDatabase.GetAssetPath(obj); string path= beginPath AssetDatabase.GetAssetPath(obj); bool resourceHot = relativalPath.IndexOf("Assets/Resources/" HotDataContext.HotDirector) == 0; bool isScene = relativalPath.IndexOf("Assets/Scenes") == 0; if (resourceHot || isScene) { if (Directory.Exists(path)) { DirectoryInfo dirinfo = new DirectoryInfo(path); FileInfo[] fs = dirinfo.GetFiles("*.*", SearchOption.AllDirectories); foreach (FileInfo f in fs) { string ext_name = Path.GetExtension(f.Name); if (ext_name == ".meta" || ext_name == ".DS_Store") continue; string childRelativalPath = f.FullName.Replace("\\", "/").Replace(Application.dataPath, "Assets"); if (isScene) { if (childRelativalPath.IndexOf("Assets/Scenes/Fix/") != -1) continue; for (int i = 0; i < scenes.Length; i ) { EditorBuildSettingsScene scene = scenes[i]; if (scene.path.Equals(childRelativalPath) && !relativalPathList.Contains(childRelativalPath)) relativalPathList.Add(childRelativalPath); } } else if (!relativalPathList.Contains(childRelativalPath)) relativalPathList.Add(childRelativalPath); } } else if (File.Exists(path)) { if (isScene) { if (relativalPath.IndexOf("Assets/Scenes/Fix/") != -1) continue; for (int i = 0; i < scenes.Length; i ) { EditorBuildSettingsScene scene = scenes[i]; if (scene.path.Equals(relativalPath)&& !relativalPathList.Contains(relativalPath)) relativalPathList.Add(relativalPath); } } else { if (!relativalPathList.Contains(relativalPath)) relativalPathList.Add(relativalPath); } } } } foreach (var relativalPath in relativalPathList) ObjDependencie(string.Empty, relativalPath); SetAbName(); } #region 建立AssetBundle [MenuItem("HotTools/建立AB包(Android)")] static void BuildAssetBundleAndroid() { BuildAssetBundle(BuildTarget.Android,false); } [MenuItem("HotTools/建立AB包(IOS)")] static void BuildAssetBundleIOS() { BuildAssetBundle(BuildTarget.iOS,false); } /// <summary> /// 建立ab包 /// </summary> /// <param name="isReBuild">是否清空重新建立</param> static void BuildAssetBundle(BuildTarget buildTarget, bool isReBuild) { string tempAB = ""; string hotUpdateSavePath = ""; if (buildTarget == BuildTarget.Android) { tempAB = beginPath "TempAB/Android"; hotUpdateSavePath = beginPath HotDataContext.HotDirector "/Android";//string.Format("{0}/{1}", Application.streamingAssetsPath, HotDataContext.HotDirector); } else { tempAB = beginPath "TempAB/Ios"; hotUpdateSavePath= beginPath HotDataContext.HotDirector "/Ios"; } string outputPath = string.Format("{0}/{1}", hotUpdateSavePath, HotDataContext.Assetbundles); if (Directory.Exists(hotUpdateSavePath)) { if (isReBuild) { Directory.Delete(hotUpdateSavePath, true); Directory.CreateDirectory(hotUpdateSavePath); } } else Directory.CreateDirectory(hotUpdateSavePath); if (Directory.Exists(tempAB)) { if (isReBuild) { Directory.Delete(tempAB, true); Directory.CreateDirectory(tempAB); } } else Directory.CreateDirectory(tempAB); BuildPipeline.BuildAssetBundles(tempAB, BuildAssetBundleOptions.ChunkBasedCompression, buildTarget);//分平台打包,可自动切换平台 if (Directory.Exists(outputPath)) { DirectoryInfo dirinfo = new DirectoryInfo(outputPath); FileInfo[] fs = dirinfo.GetFiles("*.*", SearchOption.AllDirectories); foreach (FileInfo f in fs) { string ext_name = Path.GetExtension(f.Name); if (ext_name == ".meta" || ext_name == ".DS_Store") continue; File.Delete(f.FullName); } }else Directory.CreateDirectory(outputPath); //ab目录分类 场景(Scenes)、Resources(Resources)、其他依赖ab(Others) string abResources = string.Format("{0}/{1}", outputPath, HotDataContext.ResourcesDirector); string abScenes = string.Format("{0}/{1}", outputPath, HotDataContext.ScenesDirector); string abOhters= string.Format("{0}/{1}", outputPath, HotDataContext.OhtersDirector); if (!Directory.Exists(abResources)) Directory.CreateDirectory(abResources); if (!Directory.Exists(abScenes)) Directory.CreateDirectory(abScenes); if (!Directory.Exists(abOhters)) Directory.CreateDirectory(abOhters); string[] files = Directory.GetFiles(tempAB); int ii = 0; for (int i=0; i<files.Length; i ) { string filePath = files[i]; string fileName = Path.GetFileName(filePath); string exten = Path.GetExtension(fileName); if (exten == ".manifest"||exten == ".meta") continue; ii ; EditorUtility.DisplayProgressBar("重新导入", ii.ToString(), i/ (float)files.Length); if (fileName.IndexOf(HotDataContext.resourcesAbName) == 0)//Resources里文件 { File.Copy(filePath, string.Format("{0}/{1}", abResources, fileName)); } else if (fileName.Contains(HotDataContext.sceneExten))//场景类型 { File.Copy(filePath, string.Format("{0}/{1}", abScenes, fileName)); } else if (string.IsNullOrEmpty(exten)) { //ab依赖描述 File.Copy(filePath, string.Format("{0}/{1}", outputPath, HotDataContext.Assetbundles)); } else { //其他依赖ab包 File.Copy(filePath, string.Format("{0}/{1}", abOhters, fileName)); } } EditorUtility.ClearProgressBar(); AssetDatabase.Refresh(); System.Diagnostics.Process.Start(hotUpdateSavePath); } #endregion #region 一键重新建立ab包 [MenuItem("HotTools/一键重新建立AB包(Android)")] static void OneKeyBuildABAndroid() { ClearABNames(); SetAssetBundleName(); BuildAssetBundle(BuildTarget.Android,true); } [MenuItem("HotTools/一键重新建立AB包(IOS)")] static void OneKeyBuildABIOS() { ClearABNames(); SetAssetBundleName(); BuildAssetBundle(BuildTarget.iOS,true); } #endregion }
标签: AB
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论