• unity学习笔记之不通过路径通过拖拽获取lua脚本里定义的UI组件


    哇这简直是个革命性的功能!先感谢一下某位不愿意透露姓名的贝贝大佬提供的想法和技术支持!

    先简述一下这是个啥功能,就是我们项目之前在lua里获取UI组件都是通过路径来获取,

    类似这种,定义的时候需要每个组件都复制路径不方便而且容易出错就不说了,这几天美术在重新设计原有的一些UI界面,各种调整物体父节点或者更换预制体,每次美术那边动一次都需要程序这边更改路径名字,真的挺烦,于是在大佬提示下,我这边就实现了一个可以读取lua里定义的组件,然后像C#一样直接把组件拖拽进框框里就可以了的脚本,像这样:

    (这是lua里定义的组件) 

     

    这是在脚本里解析之后,就可以直接把目标组件拖拽进来,更改路径啥的再也不用动代码了!鼓掌!撒花!

    接下来说说具体实现过程。

    大佬教的,做一个大功能需要拆分成一个个的小需求。上面这些拆成小需求就是 首先读目标lua文件的路径,然后解析定义好的字符串,把字符串转换成对应的组件类型,然后再在编辑器面板里显示出来就可以啦。

    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System.IO;
    5. using System.Text.RegularExpressions;
    6. using System;
    7. using UnityEngine.UI;
    8. using SLG.UI;
    9. using TMPro;
    10. namespace Game.UI
    11. {
    12. [System.Serializable]
    13. public class LuaUIComponentParams
    14. {
    15. public string key;
    16. public string componentType;
    17. public string node;
    18. public UnityEngine.Object obj;
    19. //public GameObject gameObject;
    20. }
    21. public class LuaUIComponent : MonoBehaviour
    22. {
    23. public string luaPath = "";
    24. public string paramsName = "ComponentParams";
    25. [HideInInspector]
    26. public List<LuaUIComponentParams> paramsList;
    27. public void ReadLuaUIComponentParams(string path)
    28. {
    29. Debug.Log(path);
    30. string text = File.ReadAllText(path);
    31. text = DeleteLog(text);
    32. text = text.Replace("\n", "");
    33. text = text.Replace("\r", "");
    34. text = text.Replace(" ", "");
    35. text = text.Replace("\"", "");
    36. text = CutOutStr(text, paramsName + "={", "}");
    37. convertStrToList(text);
    38. //Debug.Log(paramsList);
    39. }
    40. //获取指定的字符串区间
    41. private string CutOutStr(string source, string startStr = "", string endStr = "")
    42. {
    43. Regex rg;
    44. if (endStr.Equals(""))
    45. {
    46. rg = new Regex("(?<=(" + startStr + "))[.\\s\\S]*");
    47. }
    48. else if (startStr.Equals(""))
    49. {
    50. rg = new Regex(".*?(?=(" + endStr + "))");
    51. }
    52. else
    53. {
    54. rg = new Regex("(?<=(" + startStr + "))[.\\s\\S]*?(?=(" + endStr + "))");
    55. }
    56. return rg.Match(source).Value;
    57. }
    58. //删除注释
    59. private string DeleteLog(string text)
    60. {
    61. Regex stringReg = new Regex("(\".*?)--(.*?\")(.*?\n)");
    62. var ms = stringReg.Matches(text);
    63. for (int i = 0; i < ms.Count; i++)
    64. {
    65. string newString = ms[i].Value.Replace('-', '☠');
    66. text = text.Replace(ms[i].Value, newString);
    67. }
    68. stringReg = new Regex("(\'.*?)--(.*?\')(.*?\n)");
    69. ms = stringReg.Matches(text);
    70. //if (ms.Count > 0)
    71. //{
    72. // Debug.Log(file);
    73. //}
    74. for (int i = 0; i < ms.Count; i++)
    75. {
    76. string newString = ms[i].Value.Replace('-', '☠');
    77. text = text.Replace(ms[i].Value, newString);
    78. }
    79. Regex reg = new Regex(@"--\[[\c\=]*\[[\s\S]*?\][\c\=]*\]|--[\s\S]*?\n");
    80. text = reg.Replace(text, "\n");
    81. stringReg = new Regex("(\".*?)(.*?\")(.*?\n)");
    82. ms = stringReg.Matches(text);
    83. for (int i = 0; i < ms.Count; i++)
    84. {
    85. string newString = ms[i].Value.Replace('☠', '-');
    86. // Debug.Log(newString);
    87. text = text.Replace(ms[i].Value, newString);
    88. }
    89. stringReg = new Regex("(\'.*?)(.*?\')(.*?\n)");
    90. ms = stringReg.Matches(text);
    91. for (int i = 0; i < ms.Count; i++)
    92. {
    93. string newString = ms[i].Value.Replace('☠', '-');
    94. // Debug.Log(newString);
    95. text = text.Replace(ms[i].Value, newString);
    96. }
    97. return text;
    98. }
    99. //解析指定字符串,转化成List
    100. private void convertStrToList(string str)
    101. {
    102. string[] array = str.Split(',');
    103. List<LuaUIComponentParams> result = new List<LuaUIComponentParams>();
    104. foreach (var content in array)
    105. {
    106. string[] arr = content.Split(':');
    107. if (arr.Length < 2)
    108. {
    109. continue;
    110. }
    111. LuaUIComponentParams lcp = new LuaUIComponentParams();
    112. lcp.key = arr[0];
    113. lcp.componentType = arr[1];
    114. // lcp.component = convertStrToType(lcp.componentType);
    115. lcp.node = arr[2];
    116. var oldLcp = getLcpFromList(lcp.key, lcp.componentType);
    117. Debug.Log(lcp.key + " " + lcp.componentType);
    118. if (oldLcp != null)
    119. {
    120. lcp.obj = oldLcp.obj;
    121. }
    122. result.Add(lcp);
    123. }
    124. paramsList = result;
    125. }
    126. //获取原有List里的数据
    127. private LuaUIComponentParams getLcpFromList(string key, string componentType)
    128. {
    129. foreach (var param in paramsList)
    130. {
    131. if (param.key == key && param.componentType == componentType)
    132. {
    133. return param;
    134. }
    135. }
    136. return null;
    137. }
    138. //private
    139. }
    140. }

    这是组件部分的逻辑

    然后是编辑器部分的代码:

    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEditor;
    5. using UnityEngine.UI;
    6. using System;
    7. using SLG.UI;
    8. using TMPro;
    9. namespace Game.UI
    10. {
    11. [CustomEditor(typeof(LuaUIComponent))]
    12. public class LuaUIComponentEditor : Editor
    13. {
    14. public override void OnInspectorGUI()
    15. {
    16. DrawDefaultInspector();
    17. LuaUIComponent lc = (LuaUIComponent)target;
    18. if (GUILayout.Button("读取组件"))
    19. {
    20. string prvPath = Application.dataPath + "/../../../client/project_s_client/game_assets/scripts/ui/";
    21. string endPath = ".lua";
    22. string path = prvPath + lc.luaPath + endPath;
    23. lc.ReadLuaUIComponentParams(path);
    24. }
    25. if (lc.paramsList != null && lc.paramsList.Count > 0)
    26. {
    27. EditorGUILayout.BeginVertical();
    28. foreach (var param in lc.paramsList)
    29. {
    30. param.obj = EditorGUILayout.ObjectField(param.key, param.obj, convertStrToType(param.componentType), null);
    31. }
    32. EditorGUILayout.EndVertical();
    33. }
    34. if (GUI.changed)
    35. {
    36. EditorUtility.SetDirty(target);
    37. AssetDatabase.SaveAssets();
    38. EditorUtility.ClearDirty(target);
    39. }
    40. }
    41. private Type convertStrToType(string str)
    42. {
    43. switch (str)
    44. {
    45. case "Transform":
    46. return typeof(Transform);
    47. case "RectTransform":
    48. return typeof(RectTransform);
    49. case "Button":
    50. return typeof(Button);
    51. case "Image":
    52. return typeof(Image);
    53. case "GameObject":
    54. return typeof(GameObject);
    55. case "UIScrollRect":
    56. return typeof(UIScrollRect);
    57. case "UIImage":
    58. return typeof(UIImage);
    59. case "TextMeshPro":
    60. return typeof(TextMeshProUGUI);
    61. case "TMP_InputField":
    62. return typeof(TMP_InputField);
    63. case "Input":
    64. return typeof(TMP_InputField);
    65. case "Toggle":
    66. return typeof(Toggle);
    67. case "Slider":
    68. return typeof(Slider);
    69. default:
    70. return typeof(GameObject);
    71. }
    72. }
    73. }
    74. }

    比较一目了然也没啥好说的,编辑器脚本不用太考虑性能,所以获取组件部分暴力switch就可以啦。

    这个地方有一个知识点:unity监测改变是脏标记模式,改变在被用到的时候才会被监测到,所以如果不自己setDirty的话拖入组件是不会被被监测到改变的~

    今天的笔记就到这里~希望可以帮到看到这篇笔记的大家~~

  • 相关阅读:
    OneOS基于 LVGL 移植轻量化图形组件
    Redis中的数据类型
    02【SpringMVC的工作流程】
    C#WPF通知更改公共类使用实例
    右键发送到菜单+批处理实现批量自动化为文件名添加统一的后缀
    关于linux与android传输代码tcp -传文件
    mysql冷拷贝大表
    Maven项目在pom.xml里配置远程仓库
    JavaScript中的键值对数组Map对象的使用总结
    13.Spring security权限管理
  • 原文地址:https://blog.csdn.net/cactus12138/article/details/125447516