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


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

1.2 创建编辑器面板




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


2.1 参数设置修改的样式


3、在代码中使用控件,使用ObjectField和ListView
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
public class TestWindow : EditorWindow
{
private ObjectField objectField;
[MenuItem("UI Toolkit Window/TestWindow")]
public static void ShowExample()
{
TestWindow wnd = GetWindow<TestWindow>();
wnd.titleContent = new GUIContent("TestWindow");
}
public void CreateGUI()
{
// Each editor window contains a root VisualElement object
VisualElement root = rootVisualElement;
// Import UXML
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Scripts/UIToolKit/Editor/TestWindow.uxml");
VisualElement labelFromUXML = visualTree.Instantiate();
labelFromUXML.style.flexGrow = 1;
root.Add(labelFromUXML);
//获取控件
objectField = root.Q<ObjectField>("ObjectField");
//设置控件参数
objectField.objectType = typeof(GameObject);
}
}
//获取控件
listView = root.Q<ListView>("ListView");
//listView组件单个item组件创建方法绑定
listView.makeItem = MakeListItem;
//listView组件单个item绑定数据
listView.bindItem = BindListItem;
//listView组件选中item改变事件
listView.onSelectionChange += OnSelectItem;
private void OnSelectItem(IEnumerable<object> obj)
{
foreach (var item in obj)
{
GameObject go = item as GameObject;
Selection.activeObject = item as GameObject;
/*
//nameText.value = go.name;
//posText.value = go.transform.localPosition;
SerializedObject so = new SerializedObject(go);
nameText.Bind(so);
SerializedObject so2 = new SerializedObject(go.transform);
posText.Bind(so2);
*/
if(go.TryGetComponent<MyCube>(out comp))
{
var so = new SerializedObject(comp);
tempField.Bind(so);
}
else
{
tempField.Unbind();
}
}
}
private void BindListItem(VisualElement ve, int index)
{
Label label = ve as Label;
var go = sceneObjects[index];
label.text = go.name;
}
private VisualElement MakeListItem()
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.paddingLeft = 5;
return label;
}
4、数据绑定、事件监听
//数据绑定
nameText = root.Q<TextField>("NameText");
posText = root.Q<Vector3Field>("PosText");
nameText.bindingPath = "m_Name";
posText.bindingPath = "m_LocalPosition";
tempField = root.Q<IntegerField>("TempField");
tempField.bindingPath = "Temp";
//事件监听
tempTextField = root.Q<TextField>("TempTextField");
tempTextField.RegisterValueChangedCallback<string>(OnTempTextFieldValueChange);
private void OnSelectItem(IEnumerable<object> obj)
{
foreach (var item in obj)
{
GameObject go = item as GameObject;
Selection.activeObject = item as GameObject;
/*
//nameText.value = go.name;
//posText.value = go.transform.localPosition;
SerializedObject so = new SerializedObject(go);
nameText.Bind(so);
SerializedObject so2 = new SerializedObject(go.transform);
posText.Bind(so2);
*/
if(go.TryGetComponent<MyCube>(out comp))
{
var so = new SerializedObject(comp);
tempField.Bind(so);
}
else
{
tempField.Unbind();
}
}
}
private void OnTempTextFieldValueChange(ChangeEvent<string> evt)
{
Debug.Log($"Old: {evt.previousValue},_____ New: {evt.newValue}");
}
5、USS样式、Debug调试
5.1 USS样式

5.2 Debug调试

6、UI复用到Inspect面板
6.1 将内容创建为创建为VisualElement子类
using System.Collections;
using System.Collections.Generic;
using UnityEditor.UIElements;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UIElements;
public class SceneObjectPanel : VisualElement
{
private GameObject[] sceneObjects;
private ObjectField objectField;
private Button createBtn;
private Button refreshBtn;
private ListView listView;
private TextField nameText;
private Vector3Field posText;
public SceneObjectPanel()
{
// Each editor window contains a root VisualElement object
VisualElement root = this;
// Import UXML
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Scripts/UIToolKit/Editor/SceneObjectWindow.uxml");
//VisualElement labelFromUXML = visualTree.Instantiate();
//labelFromUXML.style.flexGrow = 1;
//root.Add(labelFromUXML);
visualTree.CloneTree(root);
var helpBox = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.None);
var helpBox2 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Info);
var helpBox3 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Warning);
var helpBox4 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Error);
var rightVE = root.Q<VisualElement>("right");
rightVE.Add(helpBox);
rightVE.Add(helpBox2);
rightVE.Add(helpBox3);
rightVE.Add(helpBox4);
objectField = root.Q<ObjectField>("ObjectField");
objectField.objectType = typeof(GameObject);
objectField.allowSceneObjects = false;
createBtn = root.Q<Button>("CreateBtn");
createBtn.clicked += OnCreateGameObject;
refreshBtn = root.Q<Button>("RefreshBtn");
refreshBtn.clicked += OnRefresh;
listView = root.Q<ListView>("ListView");
listView.makeItem = MakeListItem;
listView.bindItem = BindListItem;
listView.onSelectionChange += OnSelectItem;
nameText = root.Q<TextField>("NameText");
posText = root.Q<Vector3Field>("PosText");
nameText.bindingPath = "m_Name";
posText.bindingPath = "m_LocalPosition";
tempField = root.Q<IntegerField>("TempField");
tempField.bindingPath = "Temp";
tempTextField = root.Q<TextField>("TempTextField");
tempTextField.RegisterValueChangedCallback<string>(OnTempTextFieldValueChange);
var containter = new IMGUIContainer(CreateIMGUI);
rightVE.Add(containter);
//var scheduleItem = this.schedule.Execute(ScheduleAction);
//scheduleItem.Every(2000);
}
private void ScheduleAction(TimerState state)
{
Debug.Log("this is a schedule action...");
}
private void CreateIMGUI()
{
if (GUILayout.Button("IMGUI Button"))
{
Debug.Log("this is a imgui button");
}
}
private void OnTempTextFieldValueChange(ChangeEvent<string> evt)
{
Debug.Log($"Old: {evt.previousValue},_____ New: {evt.newValue}");
}
private MyCube comp;
private IntegerField tempField;
private TextField tempTextField;
private void OnSelectItem(IEnumerable<object> obj)
{
foreach (var item in obj)
{
GameObject go = item as GameObject;
Selection.activeObject = item as GameObject;
/*
//nameText.value = go.name;
//posText.value = go.transform.localPosition;
SerializedObject so = new SerializedObject(go);
nameText.Bind(so);
SerializedObject so2 = new SerializedObject(go.transform);
posText.Bind(so2);
*/
if (go.TryGetComponent<MyCube>(out comp))
{
var so = new SerializedObject(comp);
tempField.Bind(so);
}
else
{
tempField.Unbind();
}
}
}
private void BindListItem(VisualElement ve, int index)
{
Label label = ve as Label;
var go = sceneObjects[index];
label.text = go.name;
}
private VisualElement MakeListItem()
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.paddingLeft = 5;
return label;
}
private void OnRefresh()
{
Scene scene = SceneManager.GetActiveScene();
sceneObjects = scene.GetRootGameObjects();
listView.itemsSource = sceneObjects;
}
private void OnCreateGameObject()
{
GameObject prefab = objectField.value as GameObject;
var go = GameObject.Instantiate(prefab);
go.transform.position = new Vector3(Random.Range(-1.0f, 1.0f), 0, Random.Range(-1, 1));
}
}
6.2 创建子类并使用
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
[CustomEditor(typeof(MyCube))]
public class MyCubeInspector : Editor
{
public override VisualElement CreateInspectorGUI()
{
//var root = new VisualElement();
//root.Add(base.CreateInspectorGUI());
//var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Scripts/UIToolKit/Editor/SceneObjectWindow.uxml");
//VisualElement labelFromUXML = visualTree.Instantiate();
//labelFromUXML.style.flexGrow = 1;
//root.Add(labelFromUXML);
//var bas = base.CreateInspectorGUI();
//root.Add(bas);
var root = new VisualElement();
root.Add(new IMGUIContainer(OnInspectorGUI));
root.Add(new SceneObjectPanel());
return root;
}
}
7、完整代码
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
using UnityEngine.SceneManagement;
using System.Collections.Generic;
public class SceneObjectWindow : EditorWindow
{
private GameObject[] sceneObjects;
private ObjectField objectField;
private Button createBtn;
private Button refreshBtn;
private ListView listView;
private TextField nameText;
private Vector3Field posText;
[MenuItem("UI Toolkit Window/SceneObjectWindow")]
public static void ShowExample()
{
SceneObjectWindow wnd = GetWindow<SceneObjectWindow>();
wnd.titleContent = new GUIContent("SceneObjectWindow");
}
public void CreateGUI()
{
// Each editor window contains a root VisualElement object
VisualElement root = rootVisualElement;
// Import UXML
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Scripts/UIToolKit/Editor/SceneObjectWindow.uxml");
//VisualElement labelFromUXML = visualTree.Instantiate();
//labelFromUXML.style.flexGrow = 1;
//root.Add(labelFromUXML);
visualTree.CloneTree(root);
var helpBox = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.None);
var helpBox2 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Info);
var helpBox3 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Warning);
var helpBox4 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Error);
var rightVE = root.Q<VisualElement>("right");
rightVE.Add(helpBox);
rightVE.Add(helpBox2);
rightVE.Add(helpBox3);
rightVE.Add(helpBox4);
objectField = root.Q<ObjectField>("ObjectField");
objectField.objectType = typeof(GameObject);
objectField.allowSceneObjects = false;
createBtn = root.Q<Button>("CreateBtn");
createBtn.clicked += OnCreateGameObject;
refreshBtn = root.Q<Button>("RefreshBtn");
refreshBtn.clicked += OnRefresh;
//获取控件
listView = root.Q<ListView>("ListView");
//listView组件单个item组件创建方法绑定
listView.makeItem = MakeListItem;
//listView组件单个item绑定数据
listView.bindItem = BindListItem;
//listView组件选中item改变事件
listView.onSelectionChange += OnSelectItem;
//数据绑定
nameText = root.Q<TextField>("NameText");
posText = root.Q<Vector3Field>("PosText");
nameText.bindingPath = "m_Name";
posText.bindingPath = "m_LocalPosition";
tempField = root.Q<IntegerField>("TempField");
tempField.bindingPath = "Temp";
//事件监听
tempTextField = root.Q<TextField>("TempTextField");
tempTextField.RegisterValueChangedCallback<string>(OnTempTextFieldValueChange);
var containter = new IMGUIContainer(CreateIMGUI);
rightVE.Add(containter);
var scheduleItem = rootVisualElement.schedule.Execute(ScheduleAction);
scheduleItem.Every(2000);
}
private void ScheduleAction(TimerState state)
{
Debug.Log("this is a schedule action...");
}
private void CreateIMGUI()
{
if(GUILayout.Button("IMGUI Button"))
{
Debug.Log("this is a imgui button");
}
}
private void OnTempTextFieldValueChange(ChangeEvent<string> evt)
{
Debug.Log($"Old: {evt.previousValue},_____ New: {evt.newValue}");
}
private MyCube comp;
private IntegerField tempField;
private TextField tempTextField;
private void OnSelectItem(IEnumerable<object> obj)
{
foreach (var item in obj)
{
GameObject go = item as GameObject;
Selection.activeObject = item as GameObject;
/*
//nameText.value = go.name;
//posText.value = go.transform.localPosition;
SerializedObject so = new SerializedObject(go);
nameText.Bind(so);
SerializedObject so2 = new SerializedObject(go.transform);
posText.Bind(so2);
*/
if(go.TryGetComponent<MyCube>(out comp))
{
var so = new SerializedObject(comp);
tempField.Bind(so);
}
else
{
tempField.Unbind();
}
}
}
private void BindListItem(VisualElement ve, int index)
{
Label label = ve as Label;
var go = sceneObjects[index];
label.text = go.name;
}
private VisualElement MakeListItem()
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.paddingLeft = 5;
return label;
}
private void OnRefresh()
{
Scene scene = SceneManager.GetActiveScene();
sceneObjects = scene.GetRootGameObjects();
listView.itemsSource = sceneObjects;
}
private void OnCreateGameObject()
{
GameObject prefab = objectField.value as GameObject;
var go = GameObject.Instantiate(prefab);
go.transform.position = new Vector3(Random.Range(-1.0f, 1.0f), 0, Random.Range(-1, 1));
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MyCube : MonoBehaviour
{
public int Temp;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEditor.UIElements;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UIElements;
public class SceneObjectPanel : VisualElement
{
private GameObject[] sceneObjects;
private ObjectField objectField;
private Button createBtn;
private Button refreshBtn;
private ListView listView;
private TextField nameText;
private Vector3Field posText;
public SceneObjectPanel()
{
// Each editor window contains a root VisualElement object
VisualElement root = this;
// Import UXML
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Scripts/UIToolKit/Editor/SceneObjectWindow.uxml");
//VisualElement labelFromUXML = visualTree.Instantiate();
//labelFromUXML.style.flexGrow = 1;
//root.Add(labelFromUXML);
visualTree.CloneTree(root);
var helpBox = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.None);
var helpBox2 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Info);
var helpBox3 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Warning);
var helpBox4 = new HelpBox("同学们坐下,这只是一个演示!", HelpBoxMessageType.Error);
var rightVE = root.Q<VisualElement>("right");
rightVE.Add(helpBox);
rightVE.Add(helpBox2);
rightVE.Add(helpBox3);
rightVE.Add(helpBox4);
objectField = root.Q<ObjectField>("ObjectField");
objectField.objectType = typeof(GameObject);
objectField.allowSceneObjects = false;
createBtn = root.Q<Button>("CreateBtn");
createBtn.clicked += OnCreateGameObject;
refreshBtn = root.Q<Button>("RefreshBtn");
refreshBtn.clicked += OnRefresh;
listView = root.Q<ListView>("ListView");
listView.makeItem = MakeListItem;
listView.bindItem = BindListItem;
listView.onSelectionChange += OnSelectItem;
nameText = root.Q<TextField>("NameText");
posText = root.Q<Vector3Field>("PosText");
nameText.bindingPath = "m_Name";
posText.bindingPath = "m_LocalPosition";
tempField = root.Q<IntegerField>("TempField");
tempField.bindingPath = "Temp";
tempTextField = root.Q<TextField>("TempTextField");
tempTextField.RegisterValueChangedCallback<string>(OnTempTextFieldValueChange);
var containter = new IMGUIContainer(CreateIMGUI);
rightVE.Add(containter);
//var scheduleItem = this.schedule.Execute(ScheduleAction);
//scheduleItem.Every(2000);
}
private void ScheduleAction(TimerState state)
{
Debug.Log("this is a schedule action...");
}
private void CreateIMGUI()
{
if (GUILayout.Button("IMGUI Button"))
{
Debug.Log("this is a imgui button");
}
}
private void OnTempTextFieldValueChange(ChangeEvent<string> evt)
{
Debug.Log($"Old: {evt.previousValue},_____ New: {evt.newValue}");
}
private MyCube comp;
private IntegerField tempField;
private TextField tempTextField;
private void OnSelectItem(IEnumerable<object> obj)
{
foreach (var item in obj)
{
GameObject go = item as GameObject;
Selection.activeObject = item as GameObject;
/*
//nameText.value = go.name;
//posText.value = go.transform.localPosition;
SerializedObject so = new SerializedObject(go);
nameText.Bind(so);
SerializedObject so2 = new SerializedObject(go.transform);
posText.Bind(so2);
*/
if (go.TryGetComponent<MyCube>(out comp))
{
var so = new SerializedObject(comp);
tempField.Bind(so);
}
else
{
tempField.Unbind();
}
}
}
private void BindListItem(VisualElement ve, int index)
{
Label label = ve as Label;
var go = sceneObjects[index];
label.text = go.name;
}
private VisualElement MakeListItem()
{
var label = new Label();
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.paddingLeft = 5;
return label;
}
private void OnRefresh()
{
Scene scene = SceneManager.GetActiveScene();
sceneObjects = scene.GetRootGameObjects();
listView.itemsSource = sceneObjects;
}
private void OnCreateGameObject()
{
GameObject prefab = objectField.value as GameObject;
var go = GameObject.Instantiate(prefab);
go.transform.position = new Vector3(Random.Range(-1.0f, 1.0f), 0, Random.Range(-1, 1));
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
[CustomEditor(typeof(MyCube))]
public class MyCubeInspector : Editor
{
public override VisualElement CreateInspectorGUI()
{
//var root = new VisualElement();
//root.Add(base.CreateInspectorGUI());
//var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Scripts/UIToolKit/Editor/SceneObjectWindow.uxml");
//VisualElement labelFromUXML = visualTree.Instantiate();
//labelFromUXML.style.flexGrow = 1;
//root.Add(labelFromUXML);
//var bas = base.CreateInspectorGUI();
//root.Add(bas);
var root = new VisualElement();
root.Add(new IMGUIContainer(OnInspectorGUI));
root.Add(new SceneObjectPanel());
return root;
}
}
本文转载自: https://blog.csdn.net/zhoutao2333/article/details/135915275
版权归原作者 为你写首诗ge 所有, 如有侵权,请联系我们删除。
版权归原作者 为你写首诗ge 所有, 如有侵权,请联系我们删除。