2024-07-23 Unity插件 Odin Inspector11 —— 使用 Odin 自定义编辑窗口

文章目录

  • [1 OdinEditorWindow](#1 OdinEditorWindow)
    • [1.1 运作方式](#1.1 运作方式)
    • [1.2 使用特性绘制 OdinEditorWindow](#1.2 使用特性绘制 OdinEditorWindow)
    • [1.3 在 OdinEditorWindow 中渲染对象](#1.3 在 OdinEditorWindow 中渲染对象)
  • [2 OdinMenuEditorWindow](#2 OdinMenuEditorWindow)
    • [2.1 添加菜单导航栏](#2.1 添加菜单导航栏)
    • [2.2 添加导航栏示例](#2.2 添加导航栏示例)

Odin Window 可以完整地访问 Odin 绘图系统,不再需要操心 Window 的绘制 方式 ,而是专注于真正重要的事情:Window 提供的功能。

​ OdinWindow 分为两类:

  1. OdinEditorWindow

    用法与 Inspector 中使用特性自定义属性显示方式类似。

  2. OdinMenuEditorWindow

    能够创建具有左侧导航目录的窗口。本教程着重讲解如何创建 OdinMenuEditorWindow。

1 OdinEditorWindow

1.1 运作方式

​ 只需继承 OdinEditorWindow 类,而不是 EditorWindow ,就可以像使用 Odin Inspector 一样,在窗口中呈现字段、属性和方法,而无需编写任何自定义编辑器 GUI 代码。

csharp 复制代码
public class MyCustomEditorWindow : OdinEditorWindow
{
    [MenuItem("My Game/My Editor")]
    private static void OpenWindow() {
        GetWindow<MyCustomEditorWindow>().Show();
    }

    public string Hello;
}

1.2 使用特性绘制 OdinEditorWindow

​ 和 MonoBehaviour 或 ScriptableObject 一样,在 OdinEditorWindow 中对字段、属性和方法添加特性,以实现自定义绘制效果。

csharp 复制代码
public class MyCustomEditorWindow : OdinEditorWindow
{
    [MenuItem("My Game/My Editor")]
    private static void OpenWindow() {
        GetWindow<MyCustomEditorWindow>().Show();
    }

    [EnumToggleButtons, BoxGroup("Settings")]
    public ScaleMode ScaleMode;

    [FolderPath(RequireExistingPath = true), BoxGroup("Settings")]
    public string OutputPath;

    [HorizontalGroup(0.5f)]
    public List&lt;Texture&gt; InputTextures;

    [HorizontalGroup, InlineEditor(InlineEditorModes.LargePreview)]
    public Texture Preview;

    [Button(ButtonSizes.Gigantic), GUIColor(0, 1, 0)]
    public void PerformSomeAction() { }
}

1.3 在 OdinEditorWindow 中渲染对象

​ 重写 GetTarget() 方法,并为其提供任何类型的任何实例进行呈现。它不需要可序列化,甚至不需要是 Unity 对象。

csharp 复制代码
public class MyCustomEditorWindow : OdinEditorWindow
{
    [MenuItem("My Game/My Editor")]
    private static void OpenWindow() {
        GetWindow<MyCustomEditorWindow>().Show();
    }

    protected override void Initialize() {
        this.WindowPadding = Vector4.zero;
    }

    protected override object GetTarget() {
        return Selection.activeObject;
    }
}

2 OdinMenuEditorWindow

2.1 添加菜单导航栏

​ 继承 OdinMenuEditorWindow 类后,需要实现其抽象方法:BuildMenuTree(),该方法用于指定窗口左侧的导航目录显示什么内容。

csharp 复制代码
using Sirenix.OdinInspector.Editor;

public class EnemyDataEditor : OdinMenuEditorWindow
{
    protected override OdinMenuTree BuildMenuTree() {
        throw new System.NotImplementedException();
    }
}

​ 添加导航目录的方法通常有 2 种:

  1. OdinMenuTree.Add(string path, object instance)

    直接在导航目录中绘制某个对象。

    • path:导航栏名称。
    • instance:右侧绘制的对象。
  2. OdinMenuTree.AddAllAssetsAtPath( string menuPath, string assetFolderPath, Type type, bool includeSubDirectories = false, bool flattenSubDirectories = false)

    在导航目录中绘制某个目录下所有类型为 type 的对象。

    • menuPath:导航栏名称。
    • assetFolderPath:选择的目录。
    • type:对象类型。
    • includeSubDirectories:是否在子目录中也寻找对象。
    • flattenSubDirectories:如果为 true,选择的对象将不会在左侧菜单栏中依据目录折叠显示。
csharp 复制代码
public class MyCustomEditorWindow : OdinMenuEditorWindow
{
    [MenuItem("My Game/My Editor")]
    private static void OpenWindow() {
        GetWindow<MyCustomEditorWindow>().Show();
    }

    protected override OdinMenuTree BuildMenuTree() {
        var tree = new OdinMenuTree();
        tree.Selection.SupportsMultiSelect = false;

        // 方法 1
        tree.Add("Settings", GeneralDrawerConfig.Instance); 
        tree.Add("Utilities", new TextureUtilityEditor());
        
        // 方法 2
        tree.AddAllAssetsAtPath("Odin Settings", "Assets/Plugins/Sirenix", typeof(ScriptableObject), true, true);
        
        return tree;
    }
}

public class TextureUtilityEditor
{
    [BoxGroup("Tool"), HideLabel, EnumToggleButtons]
    public Tool Tool;

    public List&lt;Texture&gt; Textures;

    [Button(ButtonSizes.Large), HideIf("Tool", Tool.Rotate)]
    public void SomeAction() { }

    [Button(ButtonSizes.Large), ShowIf("Tool", Tool.Rotate)]
    public void SomeOtherAction() { }
}

2.2 添加导航栏示例

csharp 复制代码
public class MyCustomEditorWindow : OdinMenuEditorWindow
{
    [MenuItem("My Game/My Editor")]
    private static void OpenWindow() {
        GetWindow<MyCustomEditorWindow>().Show();
    }

    protected override OdinMenuTree BuildMenuTree() {
        var tree = new OdinMenuTree();
        tree.Selection.SupportsMultiSelect = false;

        OdinMenuTree tree = new OdinMenuTree(supportsMultiSelect: true) {
            { "Home", this, EditorIcons.House },
            { "Odin Settings", null, SdfIconType.GearFill },
            { "Odin Settings/ Color Palettes", ColorPaletteManager.Instance, EditorIcons.EyeDropper  },
            { "Odin Settings/ AOT Generation", AOTGenerationConfig.Instance, EditorIcons.SmartPhone  },
            { "Camera current", Camera.current },
            { "Some Class", this.someData }
        };

        tree.AddAllAssetsAtPath("Some Menu Item", "Some Asset Path", typeof(ScriptableObject), true)
            .AddThumbnailIcons();

        tree.AddAssetAtPath("Some Second Menu Item", "SomeAssetPath/ SomeAssetFile. asset");

        var customMenuItem = new OdinMenuItem(tree, "Menu Style", tree.DefaultMenuStyle);
        tree.MenuItems.Insert(2, customMenuItem);

        tree.Add("Menu/ Items/ Are/ Created/ As/ Needed", new GUIContent());
        tree.Add("Menu/ Items/ Are/ Created", new GUIContent("And can be overridden"));
        
        return tree;
    }
}
相关推荐
向宇it2 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
九鼎科技-Leo2 小时前
什么是 WPF 中的依赖属性?有什么作用?
windows·c#·.net·wpf
Heaphaestus,RC3 小时前
【Unity3D】获取 GameObject 的完整层级结构
unity·c#
芋芋qwq3 小时前
Unity UI射线检测 道具拖拽
ui·unity·游戏引擎
baivfhpwxf20234 小时前
C# 5000 转16进制 字节(激光器串口通讯生成指定格式命令)
开发语言·c#
直裾4 小时前
Scala全文单词统计
开发语言·c#·scala
tealcwu4 小时前
【Unity服务】关于Unity LevelPlay的基本情况
unity·游戏引擎
ZwaterZ5 小时前
vue el-table表格点击某行触发事件&&操作栏点击和row-click冲突问题
前端·vue.js·elementui·c#·vue
大眼睛姑娘7 小时前
Unity3d场景童话梦幻卡通Q版城镇建筑植物山石3D模型游戏美术素材
unity·游戏美术
ZwaterZ7 小时前
el-table-column自动生成序号&&在序号前插入图标
前端·javascript·c#·vue