LuaFramework:自动打包工具

本文介绍了一个Unity资源打包工具,该工具能够帮助开发者批量设置资源包名称,并通过编辑器窗口简化资源打包流程。开发者可通过此工具指定不同类型的资源文件及其路径,从而实现更高效的资源管理和打包。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.资源的创建

注意一下命名规则,一个面板及其相关的东西都放在同一个文件夹中,如果文件夹命名为xxx,则面板预制要命名为xxxPanel


2.打包

以文件夹为单位进行打包,打包类为Packager.cs。这里要打包的东西分两种,一种为图片等资源,另一种为代码资源(即lua脚本)。对lua脚本的打包已经被框架搞好了,不需要我们考虑,我们要考虑的是对前者的打包,详细的见Packager.cs的HandleExampleBundle方法,这里我做了个小工具:

  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. using UnityEditor;
  4. using System.IO;
  5. using System.Text;
  6. public enum SuffixEnum
  7. {
  8. Prefab,
  9. Png,
  10. Csv,
  11. Txt,
  12. }
  13. public class AddBuildMapUtility : EditorWindow {
  14. int count = 0;
  15. List<string> bundleNameList = new List<string>();
  16. List<SuffixEnum> suffixList = new List<SuffixEnum>();
  17. List<string> pathList = new List<string>();
  18. Vector2 scrollValue = Vector2.zero;
  19. [MenuItem("LuaFramework/AddBuildMapUtility")]
  20. static void SetAssetBundleNameExtension()
  21. {
  22. EditorWindow.GetWindow<AddBuildMapUtility>();
  23. }
  24. void OnGUI()
  25. {
  26. EditorGUILayout.BeginHorizontal();
  27. if (GUILayout.Button("添加一项"))
  28. {
  29. AddItem();
  30. }
  31. if (GUILayout.Button("清除所有项"))
  32. {
  33. Clear();
  34. }
  35. if (GUILayout.Button("读取文件(.csv)"))
  36. {
  37. Clear();
  38. string path = EditorUtility.OpenFilePanel("", Application.dataPath, "csv");
  39. string content = File.ReadAllText(path);
  40. string[] contents = content.Split(new string[] { "\r\n" }, System.StringSplitOptions.RemoveEmptyEntries);
  41. for (int i = 0; i < contents.Length; i++)
  42. {
  43. string[] a = contents[i].Split(',');
  44. AddItem(a[0], StringToEnum(a[1]), a[2]);
  45. }
  46. }
  47. if (GUILayout.Button("保存"))
  48. {
  49. string path = EditorUtility.SaveFilePanel("", Application.dataPath, "AssetBundleInfo", "csv");
  50. StringBuilder sb = new StringBuilder();
  51. for (int i = 0; i < count; i++)
  52. {
  53. if (string.IsNullOrEmpty(bundleNameList[i])) break;
  54. sb.Append(bundleNameList[i] + ",");
  55. sb.Append(EnumToString(suffixList[i]) + ",");
  56. sb.Append(pathList[i] + "\r\n");
  57. }
  58. File.WriteAllText(path, sb.ToString());
  59. AssetDatabase.Refresh();
  60. }
  61. if (GUILayout.Button("自动填写(所有选中的)"))
  62. {
  63. int startIndex = count;
  64. for (int i = 0; i < Selection.objects.Length; i++)
  65. {
  66. AddItem();
  67. AutoFill(startIndex, Selection.objects[i]);
  68. startIndex++;
  69. }
  70. }
  71. EditorGUILayout.EndHorizontal();
  72. EditorGUILayout.LabelField("注意:请以文件夹为单位进行选择!!!文件夹名即为包名!!!");
  73. scrollValue = EditorGUILayout.BeginScrollView(scrollValue);
  74. for (int i = 0; i < count; i++)
  75. {
  76. EditorGUILayout.BeginVertical();
  77. EditorGUILayout.BeginHorizontal();
  78. EditorGUILayout.LabelField(i.ToString() + "AB包名");
  79. bundleNameList[i] = EditorGUILayout.TextField("", bundleNameList[i]);
  80. suffixList[i] = (SuffixEnum)EditorGUILayout.EnumPopup("类型", suffixList[i]);
  81. pathList[i] = EditorGUILayout.TextField("路径", pathList[i]);
  82. if (GUILayout.Button("自动填写(单个)"))
  83. {
  84. AutoFill(i, Selection.objects[0]);
  85. }
  86. if (GUILayout.Button("输出路径"))
  87. {
  88. Debug.Log(pathList[i]);
  89. }
  90. if (GUILayout.Button("删除该项"))
  91. {
  92. RemoveItem(i);
  93. }
  94. EditorGUILayout.EndHorizontal();
  95. EditorGUILayout.EndVertical();
  96. }
  97. EditorGUILayout.EndScrollView();
  98. }
  99. void Clear()
  100. {
  101. count = 0;
  102. bundleNameList = new List<string>();
  103. suffixList = new List<SuffixEnum>();
  104. pathList = new List<string>();
  105. }
  106. void AddItem(string bundleName = "", SuffixEnum suffix = SuffixEnum.Prefab, string path = "")
  107. {
  108. count++;
  109. bundleNameList.Add(bundleName);
  110. suffixList.Add(suffix);
  111. pathList.Add(path);
  112. }
  113. void RemoveItem(int index)
  114. {
  115. count--;
  116. bundleNameList.Remove(bundleNameList[index]);
  117. suffixList.Remove(suffixList[index]);
  118. pathList.Remove(pathList[index]);
  119. }
  120. void AutoFill(int index, Object selectedObject)
  121. {
  122. string path = AssetDatabase.GetAssetPath(selectedObject);
  123. bundleNameList[index] = path.Remove(0, path.LastIndexOf("/") + 1).ToLower() + LuaFramework.AppConst.ExtName;
  124. string[] files = Directory.GetFiles(path);
  125. string[] temp = files[0].Split('.');
  126. suffixList[index] = StringToEnum("*." + temp[1]);
  127. pathList[index] = path;
  128. }
  129. public static string EnumToString(SuffixEnum se)
  130. {
  131. switch (se)
  132. {
  133. case SuffixEnum.Prefab:
  134. return "*.prefab";
  135. case SuffixEnum.Png:
  136. return "*.png";
  137. case SuffixEnum.Csv:
  138. return "*.csv";
  139. case SuffixEnum.Txt:
  140. return "*.txt";
  141. default:
  142. return "null";
  143. }
  144. }
  145. public static SuffixEnum StringToEnum(string s)
  146. {
  147. switch (s)
  148. {
  149. case "*.prefab":
  150. return SuffixEnum.Prefab;
  151. case "*.png":
  152. return SuffixEnum.Png;
  153. case "*.csv":
  154. return SuffixEnum.Csv;
  155. case "*.txt":
  156. return SuffixEnum.Txt;
  157. default:
  158. return SuffixEnum.Prefab;
  159. }
  160. }
  161. }





然后对HandleExampleBundle这个方法进行修改:

UGUI版本:

  1. static void HandleExampleBundle()
  2. {
  3. string resPath = AppDataPath + "/" + AppConst.AssetDir + "/";
  4. if (!Directory.Exists(resPath)) Directory.CreateDirectory(resPath);
  5. //AddBuildMap("prompt" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/Examples/Builds/Prompt");
  6. //AddBuildMap("message" + AppConst.ExtName, "*.prefab", "Assets/LuaFramework/Examples/Builds/Message");
  7. //AddBuildMap("prompt_asset" + AppConst.ExtName, "*.png", "Assets/LuaFramework/Examples/Textures/Prompt");
  8. //AddBuildMap("shared_asset" + AppConst.ExtName, "*.png", "Assets/LuaFramework/Examples/Textures/Shared");
  9. string content = File.ReadAllText(Application.dataPath + "/AssetBundleInfo.csv");
  10. string[] contents = content.Split(new string[] { "\r\n" }, System.StringSplitOptions.RemoveEmptyEntries);
  11. for (int i = 0; i < contents.Length; i++)
  12. {
  13. string[] a = contents[i].Split(',');
  14. //UnityEngine.Debug.Log(a[0]); UnityEngine.Debug.Log(a[1]); UnityEngine.Debug.Log(a[2]);
  15. AddBuildMap(a[0], a[1], a[2]);
  16. }
  17. }

那么,每一次打包,先点击LuaFramework/AddBuildMapUtility,准备好AB包的信息,然后点击LuaFramework/Build xxx Resource来进行打包,在window平台下,检查Assets\StreamingAssets中的资源是否正确。还有最重要的一点,每次对lua文件或者其他资源更改后,都要点击菜单栏LuaFramework/Build xxx Resource来重新打包!

using UnityEngine; using System; //using System.Collections; using System.Collections.Generic; using XLua; namespace LuaFramework { [LuaCallCSharp] public class AppConst { public const bool DevelopMode = false; //开发模式-不用打包资源 public const bool DebugMode = true; //调试模式,断点调试需要导入zbs /// <summary> /// 如果开启更新模式,前提必须启动框架自带服务器端。 /// 否则就需要自己将StreamingAssets里面的所有内容 /// 复制到自己的Webserver上面,并修改下面的WebUrl。 /// </summary> public static bool UpdateMode = true; //更新模式-默认关闭 public const bool LuaByteMode = false; //Lua字节码模式-默认关闭 public const bool LuaBundleMode = false; //Lua代码AssetBundle模式 public const int designWith = 1280; public const int designHeight = 720; public const int GameFrameRate = 30; //游戏帧频 public const string AppName = "Dating"; //应用程序名称 public const string LuaTempDir = "Lua/"; //临时目录 public static string AgentID = "0"; public static string ResUrl = "http://localhost:6688/"; //资源服地址 public static string WebUrl = "http://fishgame.xin"; //web服地址 public static string UIVersion = "1"; public static int GameCode = 0; public static string IpAdress = "47.238.126.161"; //服务器Ip地址 public static string IpPort = "1101"; //服务器登录端口 public static bool WeiXinLoginState = false; //启用微信登录 public static string UserId = string.Empty; //用户ID public static string MacIP = ""; public static string FrameworkRoot { get { if (UpdateMode) { return Application.persistentDataPath; }else { return Application.dataPath; } } } public static byte EOSType { get { #if UNITY_ANDROID return 3; #endif #if UNITY_IPHONE return 5; #endif #if UNITY_STANDALONE_WIN return 1; #endif } } } } 错误 1 “LuaFramework.AppConst.EOSType.get”: 并非所有的代码路径都返回值 D:\Lua_Dating546\Assets\Scripts\ConstDefine\AppConst.cs 57 13 Assembly-CSharp Assets/Scripts/ConstDefine/AppConst.cs(57,13): error CS0161: `LuaFramework.AppConst.EOSType.get': not all code paths return a value
最新发布
07-25
using UnityEngine; using System; using System.Collections; //using System.Collections.Generic; using XLua; namespace LuaFramework { [LuaCallCSharp] public class ResourceManager : Manager { public static ResourceManager _instance; public LuaFunction onDestroy; private WWW _www; private LuaFunction onProgress; void Awake() { _instance = this; } public static ResourceManager Instance { get { return _instance; } } public void CreatUIObject(string UIPath, string objname, LuaFunction callBack = null) { #if UNITY_EDITOR if (!AppConst.UpdateMode) { string path = "datingui_" + AppConst.UIVersion.ToString() + "/" + UIPath + objname; UnityEngine.Object prefab = Resources.Load(path, typeof(GameObject)); if (prefab != null) { //GameObject obj = Instantiate(Resources.Load<GameObject>(path)); //if (obj != null) //{ GameObject obj = Instantiate(prefab) as GameObject; obj.transform.localScale = Vector3.one; obj.transform.localPosition = Vector3.zero; if (callBack != null) { callBack.Call(obj); } //} }else { if (callBack != null) { callBack.Call(null); } } }else { StartCoroutine(LoadObj(AppConst.FrameworkRoot + "/datingui_" + AppConst.UIVersion + "/" + UIPath + objname + ".u3d", objname, callBack)); } #else StartCoroutine(LoadObj(AppConst.FrameworkRoot + "/datingui_" + AppConst.UIVersion + "/" + UIPath + objname + ".u3d", objname, callBack)); #endif } public void CreatGameObject(string GameName, string path, string objname, LuaFunction callBack = null) { #if UNITY_EDITOR if (!AppConst.UpdateMode) { //try //{ GameObject obj = Instantiate(Resources.Load<GameObject>("gameui"+AppConst.UIVersion+"/" + GameName + "/" + path + objname)); obj.transform.localScale = Vector3.one; obj.transform.localPosition = Vector3.zero; if (callBack != null) { callBack.Call(obj); } //}catch (Exception ex) //{ // Debug.LogError(ex.Message); //} } else { string path_ = AppConst.FrameworkRoot + "/gameui" + AppConst.UIVersion + "/" + GameName + "/" + path + objname + ".u3d"; StartCoroutine(LoadObj(path_, objname, callBack)); } #else string path_ = AppConst.FrameworkRoot + "/gameui"+AppConst.UIVersion +"/" + GameName + "/" + path + objname + ".u3d"; StartCoroutine(LoadObj(path_, objname, callBack)); #endif } public void setProgressUpdate(LuaFunction callback) { onProgress = callback; } public void resetProgressUpdate() { onProgress = null; _www = null; } float jindus = 0.0f; void Update() { #if UNITY_ANDROID if (_www != null && onProgress != null) { onProgress.Call(_www.progress); //Debug.Log(www.progress); } #else //if (jindutiao) // jindutiao.value = jindus; if (onProgress != null) { onProgress.Call(jindus); //Debug.Log(www.progress); } #endif } IEnumerator LoadObj(string bundlePath, string ObjName, LuaFunction callBack = null) { AssetBundle built = null; #if UNITY_ANDROID string path_2 = "file:///" + bundlePath; WWW www = new WWW(@path_2); if (onProgress != null) { _www = www; } yield return www; if (www.error == null) { yield return built = www.assetBundle; } else { Debug.Log("www null-------- " + path_2); } #else string path_ = bundlePath; byte[] data = null;// = OpenFile.GetFileData(path_); if (System.IO.File.Exists(path_)) { System.IO.FileStream file_ = new System.IO.FileStream(path_, System.IO.FileMode.Open, System.IO.FileAccess.Read); data = new byte[file_.Length]; int redline = 0; int allnum = 0; while (true) { byte[] reddata = new byte[1024000]; redline = file_.Read(reddata, 0, (int)reddata.Length); if (redline <= 0) { jindus = 1.0f; break; } else { //Debug.LogError(redline); System.Array.Copy(reddata, 0, data, allnum, redline); allnum += redline; jindus = (float)allnum / (float)data.Length; } yield return null; } file_.Close(); file_.Dispose(); } if (data != null) { yield return built = AssetBundle.LoadFromMemory(data); } #endif if (built != null) { GameObject obj = Instantiate(built.LoadAsset(ObjName)) as GameObject; obj.transform.localScale = Vector3.one; obj.transform.localPosition = Vector3.zero; if (callBack != null) { callBack.Call(obj); } built.Unload(false); }else { if (callBack != null) { callBack.Call(null); } } #if UNITY_ANDROID www.Dispose(); #endif } void OnDestroy() { if (onDestroy != null) { onDestroy.Call(); } } } }using UnityEngine; using System; using System.Collections; //using System.Collections.Generic; using XLua; namespace LuaFramework { [LuaCallCSharp] public class ResourceManager : Manager { public static ResourceManager _instance; public LuaFunction onDestroy; private WWW _www; private LuaFunction onProgress; void Awake() { _instance = this; } public static ResourceManager Instance { get { return _instance; } } public void CreatUIObject(string UIPath, string objname, LuaFunction callBack = null) { #if UNITY_EDITOR if (!AppConst.UpdateMode) { string path = "datingui_" + AppConst.UIVersion.ToString() + "/" + UIPath + objname; UnityEngine.Object prefab = Resources.Load(path, typeof(GameObject)); if (prefab != null) { //GameObject obj = Instantiate(Resources.Load<GameObject>(path)); //if (obj != null) //{ GameObject obj = Instantiate(prefab) as GameObject; obj.transform.localScale = Vector3.one; obj.transform.localPosition = Vector3.zero; if (callBack != null) { callBack.Call(obj); } //} }else { if (callBack != null) { callBack.Call(null); } } }else { StartCoroutine(LoadObj(AppConst.FrameworkRoot + "/datingui_" + AppConst.UIVersion + "/" + UIPath + objname + ".u3d", objname, callBack)); } #else StartCoroutine(LoadObj(AppConst.FrameworkRoot + "/datingui_" + AppConst.UIVersion + "/" + UIPath + objname + ".u3d", objname, callBack)); #endif } public void CreatGameObject(string GameName, string path, string objname, LuaFunction callBack = null) { #if UNITY_EDITOR if (!AppConst.UpdateMode) { //try //{ GameObject obj = Instantiate(Resources.Load<GameObject>("gameui"+AppConst.UIVersion+"/" + GameName + "/" + path + objname)); obj.transform.localScale = Vector3.one; obj.transform.localPosition = Vector3.zero; if (callBack != null) { callBack.Call(obj); } //}catch (Exception ex) //{ // Debug.LogError(ex.Message); //} } else { string path_ = AppConst.FrameworkRoot + "/gameui" + AppConst.UIVersion + "/" + GameName + "/" + path + objname + ".u3d"; StartCoroutine(LoadObj(path_, objname, callBack)); } #else string path_ = AppConst.FrameworkRoot + "/gameui"+AppConst.UIVersion +"/" + GameName + "/" + path + objname + ".u3d"; StartCoroutine(LoadObj(path_, objname, callBack)); #endif } public void setProgressUpdate(LuaFunction callback) { onProgress = callback; } public void resetProgressUpdate() { onProgress = null; _www = null; } float jindus = 0.0f; void Update() { #if UNITY_ANDROID if (_www != null && onProgress != null) { onProgress.Call(_www.progress); //Debug.Log(www.progress); } #else //if (jindutiao) // jindutiao.value = jindus; if (onProgress != null) { onProgress.Call(jindus); //Debug.Log(www.progress); } #endif } IEnumerator LoadObj(string bundlePath, string ObjName, LuaFunction callBack = null) { AssetBundle built = null; #if UNITY_ANDROID string path_2 = "file:///" + bundlePath; WWW www = new WWW(@path_2); if (onProgress != null) { _www = www; } yield return www; if (www.error == null) { yield return built = www.assetBundle; } else { Debug.Log("www null-------- " + path_2); } #else string path_ = bundlePath; byte[] data = null;// = OpenFile.GetFileData(path_); if (System.IO.File.Exists(path_)) { System.IO.FileStream file_ = new System.IO.FileStream(path_, System.IO.FileMode.Open, System.IO.FileAccess.Read); data = new byte[file_.Length]; int redline = 0; int allnum = 0; while (true) { byte[] reddata = new byte[1024000]; redline = file_.Read(reddata, 0, (int)reddata.Length); if (redline <= 0) { jindus = 1.0f; break; } else { //Debug.LogError(redline); System.Array.Copy(reddata, 0, data, allnum, redline); allnum += redline; jindus = (float)allnum / (float)data.Length; } yield return null; } file_.Close(); file_.Dispose(); } if (data != null) { yield return built = AssetBundle.LoadFromMemory(data); } #endif if (built != null) { GameObject obj = Instantiate(built.LoadAsset(ObjName)) as GameObject; obj.transform.localScale = Vector3.one; obj.transform.localPosition = Vector3.zero; if (callBack != null) { callBack.Call(obj); } built.Unload(false); }else { if (callBack != null) { callBack.Call(null); } } #if UNITY_ANDROID www.Dispose(); #endif } void OnDestroy() { if (onDestroy != null) { onDestroy.Call(); } } } }The referenced script on this Behaviour is missing! UnityEngine.Resources:Load(String, Type) LuaFramework.ResourceManager:CreatUIObject(String, String, LuaFunction) (at Assets/Scripts/Manager/ResourceManager.cs:36) CSObjectWrap.LuaFrameworkResourceManagerWrap:CreatUIObject(IntPtr) (at Assets/XLua/Gen/LuaFrameworkResourceManagerWrap.cs:98) XLua.LuaDLL.Lua:lua_pcall(IntPtr, Int32, Int32, Int32) XLua.DelegateBridge:SystemVoid() (at Assets/XLua/Gen/DelegatesGensBridge.cs:32) LuaFramework.LuaManager:Update() (at Assets/Scripts/Manager/LuaManager.cs:111)
07-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值