UI Tool Kit 使用

Unity 2021 已经把UIBuilder 内置了,项目组也打算 后续工具采用 toolkit来写,这边也是找了一下教程熟悉了一下。

UI 工具包 - Unity 手册

 首先 先创建一个EditorWindow

 会生成相应的C#,UXML,USS代码

 默认会把显示的MenuItem代码生成,以及Root VisualElement生成,会默认加载对应的uxml文件。

 [MenuItem("Tools/TestTool")]
    public static void ShowExample()
    {
        TestTool wnd = GetWindow<TestTool>();
        wnd.titleContent = new GUIContent("TestToolPanel");
    }

public void CreateGUI()
    {
        // Each editor window contains a root VisualElement object
        VisualElement root = rootVisualElement;

        // VisualElements objects can contain other VisualElement following a tree hierarchy.
        VisualElement label = new Label("Hello World! From C#");
        root.Add(label);

        // Import UXML
        var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Cube/delete.uxml");
        VisualElement labelFromUXML = visualTree.Instantiate();
        root.Add(labelFromUXML);

        // A stylesheet can be added to a VisualElement.
        // The style will be applied to the VisualElement and all of its children.
        var styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Cube/delete.uss");
        VisualElement labelWithStyle = new Label("Hello World! With Style");
        labelWithStyle.styleSheets.Add(styleSheet);
        root.Add(labelWithStyle);
    }

新的方式 是通过 像Root 结点添加 各种组件的方式,可以在 UIBuilder面板上操作,也可以代码添加。

 代码添加:

 var rightPart = root.Q<VisualElement>("right");
 HelpBox tipBox = new HelpBox("Test Tip", HelpBoxMessageType.Info);   
 rightPart.Add(tipBox);

想使用 面板上的 结点可以采用代码查找Name的方式:

 _objFiled = root.Q<ObjectField>("ObjectField");

 还可以给某些组件 添加事件,比如 Toggle

toggle.RegisterValueChangedCallback(TogValueChanged);

 private void TogValueChanged(ChangeEvent<bool> evt)
 {
     // evt.newValue
 }

按钮组件的 事件 绑定:

_createBtn = root.Q<Button>("CreateBtn");
_createBtn.clicked += CreateEvent;

ListView组件的使用:

 _leftList = root.Q<ListView>("LeftListView");
 //赋值
 _leftList.itemsSource = _objs;
//单个Item
 _leftList.makeItem = MakeListItem;
//数据绑定
 _leftList.bindItem = BindListItem;
   //List Item 选中事件
 _leftList.onSelectionChange += OnSelectChange;

新版UI 也支持 IMGUI嵌入

//嵌入IMGUI 
 rightPart.Add(new IMGUIContainer(() =>
  {
            if (GUILayout.Button("TestBtn"))
            {
                Debug.Log("TestLog");
            }
            
   }));              

支持计时器任务:

//计时器(默认 打开界面 就会执行)
        var scheduleItem = root.schedule.Execute(() =>
        {
            Debug.Log("Schedule Event");
        });
//间隔2秒执行一次
        //scheduleItem.Every(2000);
        //打开页面之后延迟两秒执行
        //scheduleItem.ExecuteLater(2000);

 完整代码:


    //打开页面执行一次
    public void CreateGUI()
    {
        // Each editor window contains a root VisualElement object
        VisualElement root = rootVisualElement;

        // Import UXML
        var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/Test/TestTool.uxml");
        VisualElement labelFromUXML = visualTree.Instantiate();
        root.Add(labelFromUXML);
        var rightPart = root.Q<VisualElement>("right");
        HelpBox tipBox = new HelpBox("Test Tip", HelpBoxMessageType.Info);
        
        rightPart.Add(tipBox);
        _objFiled = root.Q<ObjectField>("ObjectField");
        if (_objFiled != null)
        {
            _objFiled.objectType = typeof(GameObject);
            _objFiled.allowSceneObjects = false;
            //注册一个回调 当有变化的时候
            _objFiled.RegisterValueChangedCallback((obj) => { Debug.Log(obj.newValue.name); });
        }

        _createBtn = root.Q<Button>("CreateBtn");
        _createBtn.clicked += CreateEvent;
        _refreshBtn = root.Q<Button>("RefreshBtn");
        _refreshBtn.clicked += RefreshEvent;

        _leftList = root.Q<ListView>("LeftListView");
        
        _leftList.onSelectionChange += OnSelectChange;

        _nameText = root.Q<TextField>("NameTextField");
        _posText = root.Q<Vector3Field>("PosField");
       //数据绑定
        _nameText.bindingPath = "m_Name";
        _posText.bindingPath = "m_LocalPosition";

        //嵌入IMGUI 
        rightPart.Add(new IMGUIContainer(() =>
        {
            if (GUILayout.Button("TestBtn"))
            {
                Debug.Log("TestLog");
            }
            
        }));

        //计时器(默认 打开界面 就会执行)
        var scheduleItem = root.schedule.Execute(() =>
        {
            Debug.Log("Schedule Event");
        });

        //间隔2秒执行一次
        //scheduleItem.Every(2000);
        //打开页面之后延迟两秒执行
        //scheduleItem.ExecuteLater(2000);
    
    }

    private void OnSelectChange(IEnumerable<object> obj)
    {
        foreach (var item in obj)
        {
            GameObject go = item as GameObject;
            Selection.activeGameObject = go;
            SerializedObject serializedObj = new SerializedObject(go);
            _nameText.Bind(serializedObj);
            SerializedObject serializedTrans = new SerializedObject(go.transform);
            _posText.Bind(serializedTrans);
        }
    }

    private void BindListItem(VisualElement arg1, int index)
    {
        Label label = arg1 as Label;
        var go = _objs[index];
        label.text = go.name;
    }

    private VisualElement MakeListItem()
    {
        var label = new Label();
        label.style.unityTextAlign = TextAnchor.MiddleCenter;
        label.style.marginLeft = 5;
        return label;
    }

    private void CreateEvent()
    {
        if (_objFiled.value == null)
        {
            return;
        }
        GameObject prefab = _objFiled.value as GameObject;
        GameObject obj = Instantiate(prefab);
        obj.transform.position = new Vector3(Random.Range(0, 10), 0, Random.Range(0, 10));
    }

    private void RefreshEvent()
    {
        Scene currentScene = SceneManager.GetActiveScene();
        _objs = currentScene.GetRootGameObjects();
        _leftList.itemsSource = _objs;
        _leftList.makeItem = MakeListItem;
        _leftList.bindItem = BindListItem;
    }

   

同时UIToolKit 也支持 脚本编辑器扩展:

[CustomEditor(typeof(TestCube))]
public class TestCubeEditor : Editor
{

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
    }

    //该函数优先级大于上面
    public override VisualElement CreateInspectorGUI()
    {
        //return base.CreateInspectorGUI();
        VisualElement root = new VisualElement();
        Button testBtn = new Button();
        testBtn.style.width = 200;

        root.Add(testBtn);

        Label testLabel = new Label("TestLabel");

        root.Add(testLabel);

        Toggle tog = new Toggle();
        root.Add(tog);

        return root;
    }

}

猜你喜欢

转载自blog.csdn.net/hnzmdlhc/article/details/131258838