当前位置:   article > 正文

Unity UI Toolkit拓展编辑器

unity ui toolkit

1、项目初始化,导入UI Builder

1.1 导入UI Builder

Unity版本2020及以上才支持,2020版本需要打开preview,才能使用

 1.2 创建编辑器面板

2、使用UI Builder搭建面板结构

2.1 参数设置修改的样式

3、在代码中使用控件,使用ObjectField和ListView

  1. using UnityEditor;
  2. using UnityEngine;
  3. using UnityEngine.UIElements;
  4. using UnityEditor.UIElements;
  5. public class TestWindow : EditorWindow
  6. {
  7. private ObjectField objectField;
  8. [MenuItem("UI Toolkit Window/TestWindow")]
  9. public static void ShowExample()
  10. {
  11. TestWindow wnd = GetWindow<TestWindow>();
  12. wnd.titleContent = new GUIContent("TestWindow");
  13. }
  14. public void CreateGUI()
  15. {
  16. // Each editor window contains a root VisualElement object
  17. VisualElement root = rootVisualElement;
  18. // Import UXML
  19. var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Scripts/UIToolKit/Editor/TestWindow.uxml");
  20. VisualElement labelFromUXML = visualTree.Instantiate();
  21. labelFromUXML.style.flexGrow = 1;
  22. root.Add(labelFromUXML);
  23. //获取控件
  24. objectField = root.Q<ObjectField>("ObjectField");
  25. //设置控件参数
  26. objectField.objectType = typeof(GameObject);
  27. }
  28. }
  1. //获取控件
  2. listView = root.Q<ListView>("ListView");
  3. //listView组件单个item组件创建方法绑定
  4. listView.makeItem = MakeListItem;
  5. //listView组件单个item绑定数据
  6. listView.bindItem = BindListItem;
  7. //listView组件选中item改变事件
  8. listView.onSelectionChange += OnSelectItem;
  9. private void OnSelectItem(IEnumerable<object> obj)
  10. {
  11. foreach (var item in obj)
  12. {
  13. GameObject go = item as GameObject;
  14. Selection.activeObject = item as GameObject;
  15. /*
  16. //nameText.value = go.name;
  17. //posText.value = go.transform.localPosition;
  18. SerializedObject so = new SerializedObject(go);
  19. nameText.Bind(so);
  20. SerializedObject so2 = new SerializedObject(go.transform);
  21. posText.Bind(so2);
  22. */
  23. if(go.TryGetComponent<MyCube>(out comp))
  24. {
  25. var so = new SerializedObject(comp);
  26. tempField.Bind(so);
  27. }
  28. else
  29. {
  30. tempField.Unbind();
  31. }
  32. }
  33. }
  34. private void BindListItem(VisualElement ve, int index)
  35. {
  36. Label label = ve as Label;
  37. var go = sceneObjects[index];
  38. label.text = go.name;
  39. }
  40. private VisualElement MakeListItem()
  41. {
  42. var label = new Label();
  43. label.style.unityTextAlign = TextAnchor.MiddleLeft;
  44. label.style.paddingLeft = 5;
  45. return label;
  46. }

4、数据绑定、事件监听

  1. //数据绑定
  2. nameText = root.Q<TextField>("NameText");
  3. posText = root.Q<Vector3Field>("PosText");
  4. nameText.bindingPath = "m_Name";
  5. posText.bindingPath = "m_LocalPosition";
  6. tempField = root.Q<IntegerField>("TempField");
  7. tempField.bindingPath = "Temp";
  8. //事件监听
  9. tempTextField = root.Q<TextField>("TempTextField");
  10. tempTextField.RegisterValueChangedCallback<string>(OnTempTextFieldValueChange);
  11. private void OnSelectItem(IEnumerable<object> obj)
  12. {
  13. foreach (var item in obj)
  14. {
  15. GameObject go = item as GameObject;
  16. Selection.activeObject = item as GameObject;
  17. /*
  18. //nameText.value = go.name;
  19. //posText.value = go.transform.localPosition;
  20. SerializedObject so = new SerializedObject(go);
  21. nameText.Bind(so);
  22. SerializedObject so2 = new SerializedObject(go.transform);
  23. posText.Bind(so2);
  24. */
  25. if(go.TryGetComponent<MyCube>(out comp))
  26. {
  27. var so = new SerializedObject(comp);
  28. tempField.Bind(so);
  29. }
  30. else
  31. {
  32. tempField.Unbind();
  33. }
  34. }
  35. }
  36. private void OnTempTextFieldValueChange(ChangeEvent<string> evt)
  37. {
  38. Debug.Log($"Old: {evt.previousValue},_____ New: {evt.newValue}");
  39. }

5、USS样式、Debug调试

5.1 USS样式

5.2 Debug调试

6、UI复用到Inspect面板

6.1 将内容创建为创建为VisualElement子类

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEditor.UIElements;
  4. using UnityEditor;
  5. using UnityEngine;
  6. using UnityEngine.SceneManagement;
  7. using UnityEngine.UIElements;
  8. public class SceneObjectPanel : VisualElement
  9. {
  10. private GameObject[] sceneObjects;
  11. private ObjectField objectField;
  12. private Button createBtn;
  13. private Button refreshBtn;
  14. private ListView listView;
  15. private TextField nameText;
  16. private Vector3Field posText;
  17. public SceneObjectPanel()
  18. {
  19. // Each editor window contains a root VisualElement object
  20. VisualElement root = this;
  21. // Import UXML
  22. var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Scripts/UIToolKit/Editor/SceneObjectWindow.uxml");
  23. //VisualElement labelFromUXML = visualTree.Instantiate();
  24. //labelFromUXML.style.flexGrow = 1;
  25. //root.Add(labelFromUXML);
  26. visualTree.CloneTree(root);
  27. var helpBox = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.None);
  28. var helpBox2 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Info);
  29. var helpBox3 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Warning);
  30. var helpBox4 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Error);
  31. var rightVE = root.Q<VisualElement>("right");
  32. rightVE.Add(helpBox);
  33. rightVE.Add(helpBox2);
  34. rightVE.Add(helpBox3);
  35. rightVE.Add(helpBox4);
  36. objectField = root.Q<ObjectField>("ObjectField");
  37. objectField.objectType = typeof(GameObject);
  38. objectField.allowSceneObjects = false;
  39. createBtn = root.Q<Button>("CreateBtn");
  40. createBtn.clicked += OnCreateGameObject;
  41. refreshBtn = root.Q<Button>("RefreshBtn");
  42. refreshBtn.clicked += OnRefresh;
  43. listView = root.Q<ListView>("ListView");
  44. listView.makeItem = MakeListItem;
  45. listView.bindItem = BindListItem;
  46. listView.onSelectionChange += OnSelectItem;
  47. nameText = root.Q<TextField>("NameText");
  48. posText = root.Q<Vector3Field>("PosText");
  49. nameText.bindingPath = "m_Name";
  50. posText.bindingPath = "m_LocalPosition";
  51. tempField = root.Q<IntegerField>("TempField");
  52. tempField.bindingPath = "Temp";
  53. tempTextField = root.Q<TextField>("TempTextField");
  54. tempTextField.RegisterValueChangedCallback<string>(OnTempTextFieldValueChange);
  55. var containter = new IMGUIContainer(CreateIMGUI);
  56. rightVE.Add(containter);
  57. //var scheduleItem = this.schedule.Execute(ScheduleAction);
  58. //scheduleItem.Every(2000);
  59. }
  60. private void ScheduleAction(TimerState state)
  61. {
  62. Debug.Log("this is a schedule action...");
  63. }
  64. private void CreateIMGUI()
  65. {
  66. if (GUILayout.Button("IMGUI Button"))
  67. {
  68. Debug.Log("this is a imgui button");
  69. }
  70. }
  71. private void OnTempTextFieldValueChange(ChangeEvent<string> evt)
  72. {
  73. Debug.Log($"Old: {evt.previousValue},_____ New: {evt.newValue}");
  74. }
  75. private MyCube comp;
  76. private IntegerField tempField;
  77. private TextField tempTextField;
  78. private void OnSelectItem(IEnumerable<object> obj)
  79. {
  80. foreach (var item in obj)
  81. {
  82. GameObject go = item as GameObject;
  83. Selection.activeObject = item as GameObject;
  84. /*
  85. //nameText.value = go.name;
  86. //posText.value = go.transform.localPosition;
  87. SerializedObject so = new SerializedObject(go);
  88. nameText.Bind(so);
  89. SerializedObject so2 = new SerializedObject(go.transform);
  90. posText.Bind(so2);
  91. */
  92. if (go.TryGetComponent<MyCube>(out comp))
  93. {
  94. var so = new SerializedObject(comp);
  95. tempField.Bind(so);
  96. }
  97. else
  98. {
  99. tempField.Unbind();
  100. }
  101. }
  102. }
  103. private void BindListItem(VisualElement ve, int index)
  104. {
  105. Label label = ve as Label;
  106. var go = sceneObjects[index];
  107. label.text = go.name;
  108. }
  109. private VisualElement MakeListItem()
  110. {
  111. var label = new Label();
  112. label.style.unityTextAlign = TextAnchor.MiddleLeft;
  113. label.style.paddingLeft = 5;
  114. return label;
  115. }
  116. private void OnRefresh()
  117. {
  118. Scene scene = SceneManager.GetActiveScene();
  119. sceneObjects = scene.GetRootGameObjects();
  120. listView.itemsSource = sceneObjects;
  121. }
  122. private void OnCreateGameObject()
  123. {
  124. GameObject prefab = objectField.value as GameObject;
  125. var go = GameObject.Instantiate(prefab);
  126. go.transform.position = new Vector3(Random.Range(-1.0f, 1.0f), 0, Random.Range(-1, 1));
  127. }
  128. }

 6.2 创建子类并使用

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEditor;
  4. using UnityEngine;
  5. using UnityEngine.UIElements;
  6. [CustomEditor(typeof(MyCube))]
  7. public class MyCubeInspector : Editor
  8. {
  9. public override VisualElement CreateInspectorGUI()
  10. {
  11. //var root = new VisualElement();
  12. //root.Add(base.CreateInspectorGUI());
  13. //var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Scripts/UIToolKit/Editor/SceneObjectWindow.uxml");
  14. //VisualElement labelFromUXML = visualTree.Instantiate();
  15. //labelFromUXML.style.flexGrow = 1;
  16. //root.Add(labelFromUXML);
  17. //var bas = base.CreateInspectorGUI();
  18. //root.Add(bas);
  19. var root = new VisualElement();
  20. root.Add(new IMGUIContainer(OnInspectorGUI));
  21. root.Add(new SceneObjectPanel());
  22. return root;
  23. }
  24. }

 7、完整代码

  1. using UnityEditor;
  2. using UnityEngine;
  3. using UnityEngine.UIElements;
  4. using UnityEditor.UIElements;
  5. using UnityEngine.SceneManagement;
  6. using System.Collections.Generic;
  7. public class SceneObjectWindow : EditorWindow
  8. {
  9. private GameObject[] sceneObjects;
  10. private ObjectField objectField;
  11. private Button createBtn;
  12. private Button refreshBtn;
  13. private ListView listView;
  14. private TextField nameText;
  15. private Vector3Field posText;
  16. [MenuItem("UI Toolkit Window/SceneObjectWindow")]
  17. public static void ShowExample()
  18. {
  19. SceneObjectWindow wnd = GetWindow<SceneObjectWindow>();
  20. wnd.titleContent = new GUIContent("SceneObjectWindow");
  21. }
  22. public void CreateGUI()
  23. {
  24. // Each editor window contains a root VisualElement object
  25. VisualElement root = rootVisualElement;
  26. // Import UXML
  27. var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Scripts/UIToolKit/Editor/SceneObjectWindow.uxml");
  28. //VisualElement labelFromUXML = visualTree.Instantiate();
  29. //labelFromUXML.style.flexGrow = 1;
  30. //root.Add(labelFromUXML);
  31. visualTree.CloneTree(root);
  32. var helpBox = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.None);
  33. var helpBox2 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Info);
  34. var helpBox3 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Warning);
  35. var helpBox4 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Error);
  36. var rightVE = root.Q<VisualElement>("right");
  37. rightVE.Add(helpBox);
  38. rightVE.Add(helpBox2);
  39. rightVE.Add(helpBox3);
  40. rightVE.Add(helpBox4);
  41. objectField = root.Q<ObjectField>("ObjectField");
  42. objectField.objectType = typeof(GameObject);
  43. objectField.allowSceneObjects = false;
  44. createBtn = root.Q<Button>("CreateBtn");
  45. createBtn.clicked += OnCreateGameObject;
  46. refreshBtn = root.Q<Button>("RefreshBtn");
  47. refreshBtn.clicked += OnRefresh;
  48. //获取控件
  49. listView = root.Q<ListView>("ListView");
  50. //listView组件单个item组件创建方法绑定
  51. listView.makeItem = MakeListItem;
  52. //listView组件单个item绑定数据
  53. listView.bindItem = BindListItem;
  54. //listView组件选中item改变事件
  55. listView.onSelectionChange += OnSelectItem;
  56. //数据绑定
  57. nameText = root.Q<TextField>("NameText");
  58. posText = root.Q<Vector3Field>("PosText");
  59. nameText.bindingPath = "m_Name";
  60. posText.bindingPath = "m_LocalPosition";
  61. tempField = root.Q<IntegerField>("TempField");
  62. tempField.bindingPath = "Temp";
  63. //事件监听
  64. tempTextField = root.Q<TextField>("TempTextField");
  65. tempTextField.RegisterValueChangedCallback<string>(OnTempTextFieldValueChange);
  66. var containter = new IMGUIContainer(CreateIMGUI);
  67. rightVE.Add(containter);
  68. var scheduleItem = rootVisualElement.schedule.Execute(ScheduleAction);
  69. scheduleItem.Every(2000);
  70. }
  71. private void ScheduleAction(TimerState state)
  72. {
  73. Debug.Log("this is a schedule action...");
  74. }
  75. private void CreateIMGUI()
  76. {
  77. if(GUILayout.Button("IMGUI Button"))
  78. {
  79. Debug.Log("this is a imgui button");
  80. }
  81. }
  82. private void OnTempTextFieldValueChange(ChangeEvent<string> evt)
  83. {
  84. Debug.Log($"Old: {evt.previousValue},_____ New: {evt.newValue}");
  85. }
  86. private MyCube comp;
  87. private IntegerField tempField;
  88. private TextField tempTextField;
  89. private void OnSelectItem(IEnumerable<object> obj)
  90. {
  91. foreach (var item in obj)
  92. {
  93. GameObject go = item as GameObject;
  94. Selection.activeObject = item as GameObject;
  95. /*
  96. //nameText.value = go.name;
  97. //posText.value = go.transform.localPosition;
  98. SerializedObject so = new SerializedObject(go);
  99. nameText.Bind(so);
  100. SerializedObject so2 = new SerializedObject(go.transform);
  101. posText.Bind(so2);
  102. */
  103. if(go.TryGetComponent<MyCube>(out comp))
  104. {
  105. var so = new SerializedObject(comp);
  106. tempField.Bind(so);
  107. }
  108. else
  109. {
  110. tempField.Unbind();
  111. }
  112. }
  113. }
  114. private void BindListItem(VisualElement ve, int index)
  115. {
  116. Label label = ve as Label;
  117. var go = sceneObjects[index];
  118. label.text = go.name;
  119. }
  120. private VisualElement MakeListItem()
  121. {
  122. var label = new Label();
  123. label.style.unityTextAlign = TextAnchor.MiddleLeft;
  124. label.style.paddingLeft = 5;
  125. return label;
  126. }
  127. private void OnRefresh()
  128. {
  129. Scene scene = SceneManager.GetActiveScene();
  130. sceneObjects = scene.GetRootGameObjects();
  131. listView.itemsSource = sceneObjects;
  132. }
  133. private void OnCreateGameObject()
  134. {
  135. GameObject prefab = objectField.value as GameObject;
  136. var go = GameObject.Instantiate(prefab);
  137. go.transform.position = new Vector3(Random.Range(-1.0f, 1.0f), 0, Random.Range(-1, 1));
  138. }
  139. }
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class MyCube : MonoBehaviour
  5. {
  6. public int Temp;
  7. // Start is called before the first frame update
  8. void Start()
  9. {
  10. }
  11. // Update is called once per frame
  12. void Update()
  13. {
  14. }
  15. }
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEditor.UIElements;
  4. using UnityEditor;
  5. using UnityEngine;
  6. using UnityEngine.SceneManagement;
  7. using UnityEngine.UIElements;
  8. public class SceneObjectPanel : VisualElement
  9. {
  10. private GameObject[] sceneObjects;
  11. private ObjectField objectField;
  12. private Button createBtn;
  13. private Button refreshBtn;
  14. private ListView listView;
  15. private TextField nameText;
  16. private Vector3Field posText;
  17. public SceneObjectPanel()
  18. {
  19. // Each editor window contains a root VisualElement object
  20. VisualElement root = this;
  21. // Import UXML
  22. var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Scripts/UIToolKit/Editor/SceneObjectWindow.uxml");
  23. //VisualElement labelFromUXML = visualTree.Instantiate();
  24. //labelFromUXML.style.flexGrow = 1;
  25. //root.Add(labelFromUXML);
  26. visualTree.CloneTree(root);
  27. var helpBox = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.None);
  28. var helpBox2 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Info);
  29. var helpBox3 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Warning);
  30. var helpBox4 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Error);
  31. var rightVE = root.Q<VisualElement>("right");
  32. rightVE.Add(helpBox);
  33. rightVE.Add(helpBox2);
  34. rightVE.Add(helpBox3);
  35. rightVE.Add(helpBox4);
  36. objectField = root.Q<ObjectField>("ObjectField");
  37. objectField.objectType = typeof(GameObject);
  38. objectField.allowSceneObjects = false;
  39. createBtn = root.Q<Button>("CreateBtn");
  40. createBtn.clicked += OnCreateGameObject;
  41. refreshBtn = root.Q<Button>("RefreshBtn");
  42. refreshBtn.clicked += OnRefresh;
  43. listView = root.Q<ListView>("ListView");
  44. listView.makeItem = MakeListItem;
  45. listView.bindItem = BindListItem;
  46. listView.onSelectionChange += OnSelectItem;
  47. nameText = root.Q<TextField>("NameText");
  48. posText = root.Q<Vector3Field>("PosText");
  49. nameText.bindingPath = "m_Name";
  50. posText.bindingPath = "m_LocalPosition";
  51. tempField = root.Q<IntegerField>("TempField");
  52. tempField.bindingPath = "Temp";
  53. tempTextField = root.Q<TextField>("TempTextField");
  54. tempTextField.RegisterValueChangedCallback<string>(OnTempTextFieldValueChange);
  55. var containter = new IMGUIContainer(CreateIMGUI);
  56. rightVE.Add(containter);
  57. //var scheduleItem = this.schedule.Execute(ScheduleAction);
  58. //scheduleItem.Every(2000);
  59. }
  60. private void ScheduleAction(TimerState state)
  61. {
  62. Debug.Log("this is a schedule action...");
  63. }
  64. private void CreateIMGUI()
  65. {
  66. if (GUILayout.Button("IMGUI Button"))
  67. {
  68. Debug.Log("this is a imgui button");
  69. }
  70. }
  71. private void OnTempTextFieldValueChange(ChangeEvent<string> evt)
  72. {
  73. Debug.Log($"Old: {evt.previousValue},_____ New: {evt.newValue}");
  74. }
  75. private MyCube comp;
  76. private IntegerField tempField;
  77. private TextField tempTextField;
  78. private void OnSelectItem(IEnumerable<object> obj)
  79. {
  80. foreach (var item in obj)
  81. {
  82. GameObject go = item as GameObject;
  83. Selection.activeObject = item as GameObject;
  84. /*
  85. //nameText.value = go.name;
  86. //posText.value = go.transform.localPosition;
  87. SerializedObject so = new SerializedObject(go);
  88. nameText.Bind(so);
  89. SerializedObject so2 = new SerializedObject(go.transform);
  90. posText.Bind(so2);
  91. */
  92. if (go.TryGetComponent<MyCube>(out comp))
  93. {
  94. var so = new SerializedObject(comp);
  95. tempField.Bind(so);
  96. }
  97. else
  98. {
  99. tempField.Unbind();
  100. }
  101. }
  102. }
  103. private void BindListItem(VisualElement ve, int index)
  104. {
  105. Label label = ve as Label;
  106. var go = sceneObjects[index];
  107. label.text = go.name;
  108. }
  109. private VisualElement MakeListItem()
  110. {
  111. var label = new Label();
  112. label.style.unityTextAlign = TextAnchor.MiddleLeft;
  113. label.style.paddingLeft = 5;
  114. return label;
  115. }
  116. private void OnRefresh()
  117. {
  118. Scene scene = SceneManager.GetActiveScene();
  119. sceneObjects = scene.GetRootGameObjects();
  120. listView.itemsSource = sceneObjects;
  121. }
  122. private void OnCreateGameObject()
  123. {
  124. GameObject prefab = objectField.value as GameObject;
  125. var go = GameObject.Instantiate(prefab);
  126. go.transform.position = new Vector3(Random.Range(-1.0f, 1.0f), 0, Random.Range(-1, 1));
  127. }
  128. }
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEditor;
  4. using UnityEngine;
  5. using UnityEngine.UIElements;
  6. [CustomEditor(typeof(MyCube))]
  7. public class MyCubeInspector : Editor
  8. {
  9. public override VisualElement CreateInspectorGUI()
  10. {
  11. //var root = new VisualElement();
  12. //root.Add(base.CreateInspectorGUI());
  13. //var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Scripts/UIToolKit/Editor/SceneObjectWindow.uxml");
  14. //VisualElement labelFromUXML = visualTree.Instantiate();
  15. //labelFromUXML.style.flexGrow = 1;
  16. //root.Add(labelFromUXML);
  17. //var bas = base.CreateInspectorGUI();
  18. //root.Add(bas);
  19. var root = new VisualElement();
  20. root.Add(new IMGUIContainer(OnInspectorGUI));
  21. root.Add(new SceneObjectPanel());
  22. return root;
  23. }
  24. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/808849
推荐阅读
相关标签
  

闽ICP备14008679号