• unity基础2-编辑器拓展


    UI Toolkit 编辑器拓展

    官网文档
    使用 UI Toolkit 可以在 unity 中自定义一些 UI 工具,可以在运行时或编辑器状态下运行。例如,农场经营类游戏可以写一个物品编辑器 ItemEditor,卡牌类游戏可以写卡牌编辑器。
    卡牌编辑器

    官网也有案例
    在这里插入图片描述

    物品编辑器

    对于农场经验项目,写一个物品编辑器 (麦田物语课程) ,方便我们操作 CropDataList 数据库(scriptableobject),增、删、改物品数据。
    Editor Window 创建编辑器窗口
    在这里插入图片描述
    UI Document可以用于创建物品的模板
    在这里插入图片描述
    C#
    该文件是物品编辑器的主要脚本
    UXML
    该文件类似于 HTML 一样,描述物品编辑器的内容
    双击,默认使用 UI Builder 打开编辑窗口
    已经绘制完成的物品编辑器
    USS
    该文件类似于 CSS ,描述物品编辑器的样式


    基本操作步骤:
    Library 窗口 包含各种控件,一般先用 VisualElement 做容器,里面再放置一些 Lable Button 等控件
    Hierarchy 窗口 包含各个控件的层级信息
    Viewport 窗口 预览当前物品编辑器的内容

    创建窗口

    《ItemEditor.cs》

    public class ItemEditor : EditorWindow
    {
    	// 在菜单栏显示物品编辑器选项
        // [MenuItem("Window/UI Toolkit/ItemEditor")]
        [MenuItem("My Tools/ItemEditor")]
        public static void ShowExample()
        {
            ItemEditor wnd = GetWindow<ItemEditor>();
            wnd.titleContent = new GUIContent("ItemEditor");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    加载 uxml

    public void CreateGUI()
    {
    	// Each editor window contains a root VisualElement object
        VisualElement root = rootVisualElement;
    	// Import UXML
        var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/UIBuilder/ItemEditor.uxml");
        VisualElement labelFromUXML = visualTree.Instantiate();
        root.Add(labelFromUXML);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    绑定数据

    先确定 Hierarchy 窗口中各个组件的层级顺序,查找控件
    查询控件,从 root 节点根据类型 ListView 和名称 ItemList ,查找对于控件

    // 取得我们在物品编辑器中绘制的左边栏 listview
    private ListView listView;
    // 物品编辑器的右侧详情栏
    private ScrollView itemDetailsSection;
    
    ...
    
    // 找到物品编辑器中的左边栏
    listView = root.Q<VisualElement>("ItemList").Q<ListView>("ListViewer");
    itemDetailsSection = root.Q<ScrollView>("ItemDetails");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    绑定回调,在编辑物品数据时,自动将数据写回数据库
    回调的写法可以参考官方的例子
    在这里插入图片描述


    	itemNameField.RegisterCallback<ChangeEvent<string>>(
                evt =>
                {
                    activeItem.itemName = evt.newValue;
                    // 更改名称后刷新左侧物品栏名称
                    listView.Rebuild();
                }
            );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    加载数据

    加载物品数据

    	// 加载物品数据库
        private void LoadDatabase()
        {
            // 找到的是 GUID 字符串
            var dataArray = AssetDatabase.FindAssets("t:ItemListSO");
            // 其他版本使用字符串 ItemListSO 也行
            if (dataArray.Length > 0)
            {
                dataArray[0] = AssetDatabase.GUIDToAssetPath(dataArray[0]);
                database = AssetDatabase.LoadAssetAtPath<ItemListSO>(dataArray[0]);
            }
    
            itemList = database.itemDetailsList;
    
            // 为了修改文件数据,必须标记该对象
            EditorUtility.SetDirty(database);
    
            // 加载 cropData 不希望在 editor window 中修改其中内容,只读取
            dataArray = AssetDatabase.FindAssets("t:CropDataList_SO");
            if (dataArray.Length > 0)
            {
                dataArray[0] = AssetDatabase.GUIDToAssetPath(dataArray[0]);
                cropDatabase = AssetDatabase.LoadAssetAtPath<CropDataList_SO>(dataArray[0]);
            }
    
            cropDetailList = cropDatabase.cropDetailsList;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    生成物品

    参考例子,生成左侧物品列表

    	private void GenerateListView()
        {
            Func<VisualElement> makeItem = () => itemTemplate.CloneTree();
            Action<VisualElement, int> bindItem = (e, i) =>
            {
                if (i < itemList.Count)
                {
                    if (itemList[i].itemIcon != null)
                    {
                        e.Q<VisualElement>("ItemIcon").style.backgroundImage = itemList[i].itemIcon.texture;
                    }
                    e.Q<Label>("ItemName").text = itemList[i].itemName == null ? "No Item" : itemList[i].itemName;
                }
            };
            listView.fixedItemHeight = 56;
            listView.itemsSource = itemList;
            listView.makeItem = makeItem;
            listView.bindItem = bindItem;
    
            listView.onSelectionChange += OnListSectionChange;
            // 未选择左侧物品时,不显示右侧详情栏
            itemDetailsSection.visible = false;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    如果选择了左侧某一个物品,自动生成右侧物品详情

    	private void OnListSectionChange(IEnumerable<object> obj)
        {
            // 选中选项时传递的参数 obj 表示选中的一个或多个物体 因此取第一个物体表示当前选择的一个物体
            activeItem = obj.First() as ItemDetails;
            // 标记后可以执行编辑、撤销等操作
            itemDetailsSection.MarkDirtyRepaint();
            GetItemDetails();
            itemDetailsSection.visible = true;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    js焦点处理的几种方式
    解决mac系统终端无法使用vpn
    区块链产业快速发展 和数集团开启区块链应用新时代
    线程间等待与唤醒机制、单例模式、阻塞队列、定时器
    关于HM NISEDIT在新版系统下编译并运行提示权限不足问题的解决方案
    ssm基于web的网络租房系统毕业设计源码250910
    音频数据集1--LJSpeech单人语音
    RabbitMQ消息可靠性保证机制--发送端确认
    时间序列预测模型实战案例(十)(个人创新模型)通过堆叠CNN、GRU、LSTM实现多元预测和单元预测
    基于Python实现k-means算法和混合高斯模型
  • 原文地址:https://blog.csdn.net/qq_42534809/article/details/125456780