一、MenuItem:创建菜单项

  (1) 描述
  MenuItem属性可以让你在主菜单和inspector context菜单中添加菜单项。
  MenuItem属性可以将任何static函数转换为菜单命令。只有static函数可以使用MenuItem属性。
  创建热键,可以使用以下特殊字符:%(在Windows上表示ctrl,在macOS表示cmd),#(shift)和&(alt)。如果不需要特殊的修饰键组合,则可以在下划线后给出该组合键。例如,菜单绑定快捷键shift-alt-g,可使用"MyMenu/Do Something #&g"。若要创建带有热键g且没有按键修饰符的菜单项,可使用 “MyMenu/Do Something _g”。
  也支持一些特殊的键盘键作为热键,例如“ #LEFT”被映射为左移。支持特殊键如下:LEFT,RIGHT,UP,DOWN,F1 … F12,HOME,END,PGUP,PGDN。
  热键文本之前必须带有空格字符(例如"MyMenu/Do_g"中g不会被解释为热键,而"MyMenu/Do _g"会被解释为热键)。
  将菜单项添加到“ GameObject /”菜单中以创建自定义游戏对象时,确保调用GameObjectUtility.SetParentAndAlign以确保在上下文单击的情况下正确地重新创建了新的GameObject(可参见下面的示例)。函数还应该调用 Undo.RegisterCreatedObjectUndo以创建可撤消的命令,并调用Selection.activeObject 以使新创建的对象被选中。注意,为了将“ GameObject /”中的菜单项传播到hierarchy的Create下拉菜单和hierarchy context菜单中,必须将其与其他GameObject创建菜单项分组。可以通过将其优先级设置为10来实现(请参见下面的示例)。注意,出于传统目的,“ GameObject / Create Other”中未设置显式优先级的MenuItems将获得优先级10,而不是默认的1000-我们鼓励使用比“ Create Other”更具描述性的类别名称,并将显式优先级设置为10 。

  创建菜单项

public class EditorTest
{
    //在测试菜单中添加测试菜单项
    [MenuItem("测试/测试")]
    static void DoSomething()
    {
        Debug.Log("测试...");
    }
}

unity 自定义enum unity 自定义快捷键_函数定义


  创建带启用条件的菜单项

using UnityEditor;
using UnityEngine;

public class EditorTest
{
    //需条件才能点击的菜单项
    [MenuItem("测试/测试")]
    static void DoSomething()
    {
        Debug.Log("测试...");
    }
    //上面菜单的条件
    [MenuItem("测试/测试", true)]
    static bool ValidateDoSomething()
    {
        return Selection.activeTransform != null;
    }
}

unity 自定义enum unity 自定义快捷键_unity 自定义enum_02


  创建带快捷键的菜单项

using UnityEditor;
using UnityEngine;

public class EditorTest
{
    //添加带有快捷键的菜单(在windows为ctrl-g,在macOS为cmd-g)
    [MenuItem("测试/测试 %g")]
    static void DoSomething()
    {
        Debug.Log("测试...");
    }
}
//按住ctrl+g输出测试...

  创建组件CONTENT菜单

public class EditorTest
{
    //添加CONTEXT菜单
    [MenuItem("CONTEXT/Transform/测试")]
    static void DoSomething(MenuCommand conmand)
    {
        Transform body = (Transform)conmand.context;
        body.position = new Vector3(10, 10, 10);
        Debug.Log("设置Transform position为 " + body.position);
    }
}

unity 自定义enum unity 自定义快捷键_菜单项_03


  创建GameObje菜单

//File、Editor、Assets、Component、Window、Help菜单同理,只需吧GameObject改成对应的即可。
using UnityEditor;
using UnityEngine;

public class EditorTest
{
    //添加GameObject菜单项,并设置菜单项位置,但如何控制GameObject/测试的位置?
    //[MenuItem("GameObject/测试", false, 0)]
    //[MenuItem("GameObject/测试", false, 1)]
    [MenuItem("GameObject/测试/测试0", false, 0)]
    static void CreateCustomGameObject0(MenuCommand conmand)
    {
        GameObject go = new GameObject("Custom Game Object1");
        //设置新建物体未选中物体的子节点
        GameObjectUtility.SetParentAndAlign(go, conmand.context as GameObject);
        Undo.RegisterCreatedObjectUndo(go, "Create" + go.name);
        Selection.activeObject = go;
    }

    [MenuItem("GameObject/测试/测试1", false, 11)]
    static void CreateCustomGameObject1(MenuCommand conmand)
    {
        GameObject go = new GameObject("Custom Game Object1");
        //设置新建物体未选中物体的子节点
        GameObjectUtility.SetParentAndAlign(go, conmand.context as GameObject);
        Undo.RegisterCreatedObjectUndo(go, "Create" + go.name);
        Selection.activeObject = go;
    }
    //与上一个菜单间隔11个单位有分割线
    [MenuItem("GameObject/测试/测试2", false, 22)]
    static void CreateCustomGameObject2(MenuCommand conmand)
    {
        GameObject go = new GameObject("Custom Game Object2");
        //设置新建物体未选中物体的子节点
        GameObjectUtility.SetParentAndAlign(go, conmand.context as GameObject);
        Undo.RegisterCreatedObjectUndo(go, "Create" + go.name);
        Selection.activeObject = go;
    }
}

unity 自定义enum unity 自定义快捷键_ide_04


unity 自定义enum unity 自定义快捷键_ide_05


unity 自定义enum unity 自定义快捷键_ide_06


  (2) Constructors

MenuItem:创建一个菜单项,并在菜单项选中的时候调用其对应的static函数。MenuItem是脚本函数之前的属性。这使该函数出现在Unity菜单系统中。菜单位置由itemName 参数指定。isValidateFunction用于使MenuItem函数成为具有相同itemName参数的脚本函数之前执行的函数。第二个参数是布尔值。如果将此参数设置为该参数true,它将把关联的函数标记为在执行第二个脚本函数之前调用的函数。第二个具有相同功能的脚本功能itemName将在接下来执行。priority确定如何在菜单系统中排序对应的脚本函数。将该整数值与其他脚本函数上的值进行比较。如果该整数值大于其他值,则MenuItem脚本函数将位于列表的底部。priority还可以用于将脚本功能列表分为几组进行管理。
函数定义:
1.public MenuItem(string itemName);
2.public MenuItem(stirng itemName, bool isValidateFunction);
3.public MenuItem(string itemName, bool isValidateFunciton, int priority);
函数参数:
1.itemName:该itemName是类似菜单项路径的名称。例如,菜单项可以是“ GameObject/Do Something”。
2.isValidateFunction:如果isValidateFunction为true,则这是一个菜单项的验证函数,在调用相同itemName的菜单项函数时会先调用此验证函数。
3.priority:菜单项的显示顺序。
代码示例1:
using UnityEditor;
using UnityEngine;

public class EditorTest
{
    //添加菜单项1
    [MenuItem("测试/测试1",false, 100)]
    static void Example1()
    {
        Debug.Log("测试1...");
    }
    //添加菜单项2
    [MenuItem("测试/测试2", false, 100)]
    static void Example2()
    {
        Debug.Log("测试2...");
    }
}
代码示例2:下面这个示例显示了测试菜单如何用分割线分割菜单项。当priority参数间隔超过10个时,就会发生这种情况。注意大于10才能在菜单中创建分割线。但是按照下面的例子,脚本函数之间的优先级差值需要大于等于11.若将下面的111改为110则没有分割线。
using UnityEditor;
using UnityEngine;

public class EditorTest
{
    //添加菜单项1
    [MenuItem("测试/测试1",false, 100)]
    static void Example1()
    {
        Debug.Log("测试1...");
    }
    //添加菜单项2
    [MenuItem("测试/测试2", false, 111)]
    static void Example2()
    {
        Debug.Log("测试2...");
    }
}

unity 自定义enum unity 自定义快捷键_菜单项_07


二、ScriptableObject:创建保存数据的asset

  (1) 描述

  如果要创建不需要附加到游戏对象上的对象,可以派生一个类。

  这对于仅用于存储数据的资产很有用。

  要创建绑定到项目中资产的ScriptableObject实例,可使用CreateAssetMenuAttribute属性。

  此类不支持null-conditional operator (?.) 和 null-coalescing operator (??) 。

  (2) Static Methods

CreateInstance:创建scriptable对象的实例。若要通过Editor用户界面创建绑定到.asset文件的ScriptableObject实例,可使用CreateAssetMenuAttribute。
函数定义:
1.public static ScriptableObject CreateInstance(string className);
2.public static ScriptableObject CreateInstance(Type type);
3.public static T CreateInstance();
函数参数:
1.className:要创建的ScriptableObject的type对应的名称。
2.type:要创建的ScriptableObject的类型,System.Type实例。
函数返回值:
ScriptableObject:创建的ScriptableObject
T:创建的ScriptableObject

  (3) Message

Awake:启动ScriptableObject脚本时将调用此函数。ScriptableObject脚本启动时将调用Awake。 这是在游戏启动时发生的,类似于MonoBehavior.Awake。
函数定义:ScriptableObject.Awake()
代码示例:第一个是ScriptableObject脚本。 这实现了与MonoBehaviour分开的代码。 第二个是与MonoBehaviour相关的小型脚本,该脚本从ScriptableObject脚本访问值。

using UnityEngine;

//添加菜单项到Assets/Create
[CreateAssetMenuAttribute]
//[CreateAssetMenu]
//一个ScriptableObject示例脚本。
// A和B成员变量实现与MonoBehaviour无关的功能。
public class ScriptObjExample : ScriptableObject
{
    int a = 10;
    int[] b = new int[5] { 0, 17, 34, 42, 67 };
    public int A
    {
        get { return a; }
    }
    //返回b数组中的值;如果x超出范围,则返回-1
    public int B(int x)
    {
        if (x >= 0 && x <= 5)
            return b[x];
        else
            return -1;
    }
    //创建Asset以及CreateInstance的时候会调用Awake->OnEnable
    public void Awake()
    {
        Debug.Log("ScriptObjExample Awake");
    }
    public void OnEnable()
    {
        Debug.Log("ScriptObjExample OnEnable");
    }
    //调用CreateInstance后,游戏停止运行会调用OnDisable->OnDestroy
    public void OnDisable()
    {
        Debug.Log("ScriptObjExample OnDisable");
    }
    public void OnDestroy()
    {
        Debug.Log("ScriptObjExample OnDestroy");
    }
}

//创建和访问ScriptableObjectTest
public class ScriptableObjectTest : MonoBehaviour
{
    ScriptObjExample test;
    private void Start()
    {
        Debug.Log("ScriptableObjectTest Start");
        test = (ScriptObjExample)ScriptableObject.CreateInstance(typeof(ScriptObjExample));
        print(test.A);
        print(test.B(3));
        print(test.B(-3));
    }
}
OnDestroy:当scriptable的对象将被销毁时,将调用此函数。OnDestroy不能是协程co-routine。
函数定义:ScriptableObject.OnDestroy()
代码示例:同上
OnDisable:当scriptable的对象超出范围时,将调用此函数。当对象被销毁时也调用该方法,该方法可用于任何清除代码。 编译完成后重新加载脚本时,将调用OnDisable,并在加载脚本后调用OnEnable。OnDisable不能是协程co-routine。
函数定义:ScriptableObject.OnDisable()
代码示例:同上
OnEnable:加载对象时调用此函数。OnEnable不能是协程co-routine。
函数定义:ScriptableObject.OnEnable()
代码示例:同上

  (4) CreateAssetMenuAttribute
    (1) 描述
    将ScriptableObject派生的类型在"Assets / Create"子菜单中列出,点击子菜单时可以创建该类型的实例并将其存储为“ .asset”文件。
    (2) Properties

fileName:此类型新创建实例使用的默认文件名。注意,任何自定义文件名都必须以“ .asset”结尾,这样才能被Unity正确处理。
函数定义:public string fileName;
menuName:"Assets/Create"菜单中该类型显示的名称。与其他菜单项代码一样,使用正斜杠(“ /”)路径分隔符将项分组为子菜单。 例如,将MenuName指定为“ Gameplay / Objective”将导致该类型的菜单项在“ Create”的子菜单“ Gameplay”的子菜单“ Objective”中。
函数定义:public string menuName;
order:菜单项在“Assets/Create”菜单中的位置。
函数定义:public int order;

三、SettingsProvider:创建Setting/Preferences菜单项

  (1) 描述
  SettingsProvider是配置类,用于指定应如何在“Setting”或“Preferences”窗口中显示Project setting或prefeerence。
  为了添加新的Project setting或preference页面,可定义一个SettingsProvider。 SettingsProvider类提供了钩子来显示任何UI(使用IMGUI或UIElements绘制它)。 它还提供了一个API,该API允许您以两种方式指定在“Setting”和“Preferences”窗口中使用的关键字:
  1)搜索栏过滤掉没有匹配关键字的SettingsProviders。
  2)属性标签以匹配的关键字突出显示。

  代码示例

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

//创建新类型Setting Asset
class MyCustomSettings : ScriptableObject
{
    public const string k_MyCustomSettingsPath = "Assets/Editor/MyCustomSettings.asset";
    [SerializeField] private int m_Number;
    [SerializeField] private string m_SomeString;
    internal static MyCustomSettings GetOrCreateSetting()
    {
        var settings = AssetDatabase.LoadAssetAtPath<MyCustomSettings>(k_MyCustomSettingsPath);
        if (settings == null)
        {
            settings = ScriptableObject.CreateInstance<MyCustomSettings>();
            settings.m_Number = 42;
            settings.m_SomeString = "The answer to the universe";
            AssetDatabase.CreateAsset(settings, k_MyCustomSettingsPath);
            AssetDatabase.SaveAssets();
        }
        return settings;
    }
    internal static SerializedObject GetSerializedSettings()
    {
        return new SerializedObject(GetOrCreateSetting());
    }
}

//使用IMGUI为绘图框架注册SettingsProvider:
static class MyCustomSettingsIMGUIRegister
{
    [SettingsProvider]
    public static SettingsProvider CreateMyCustomSettingsProvider()
    {
        //第一个参数是Setting窗口中的路径
        //第二个参数是此设置的范围:它仅出现在Project Setting窗口中。
        var provider = new SettingsProvider("Project/MyCustomIMGUISettings", SettingsScope.Project)
        {
            //默认情况下,如果未提供label,则路径的最后一个字段用作显示名称。
            label = "Custom IMGUI",
            //创建SettingsProvider并用它初始化其绘制(IMGUI)函数:
            guiHandler = (searchContext) =>
            {
                var settings = MyCustomSettings.GetSerializedSettings();
                EditorGUILayout.PropertyField(settings.FindProperty("m_Number"), new GUIContent("My Number"));
                EditorGUILayout.PropertyField(settings.FindProperty("m_SomeString"), new GUIContent("My String"));
            },
            //填充搜索关键字以启用智能过滤搜索并突出显示标签:
            keywords = new HashSet<string>(new[] { "Number", "Some String" })
        };
        return provider;
    }
}

unity 自定义enum unity 自定义快捷键_ide_08

using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor;
using System.Collections.Generic;

//创建新类型Setting Asset
class MyCustomSettings : ScriptableObject
{
    public const string k_MyCustomSettingsPath = "Assets/Editor/MyCustomSettings.asset";
    [SerializeField] private int m_Number;
    [SerializeField] private string m_SomeString;
    internal static MyCustomSettings GetOrCreateSetting()
    {
        var settings = AssetDatabase.LoadAssetAtPath<MyCustomSettings>(k_MyCustomSettingsPath);
        if (settings == null)
        {
            settings = ScriptableObject.CreateInstance<MyCustomSettings>();
            settings.m_Number = 42;
            settings.m_SomeString = "The answer to the universe";
            AssetDatabase.CreateAsset(settings, k_MyCustomSettingsPath);
            AssetDatabase.SaveAssets();
        }
        return settings;
    }
    internal static SerializedObject GetSerializedSettings()
    {
        return new SerializedObject(GetOrCreateSetting());
    }
}
//使用UIElements为绘图框架注册SettingsProvider:
static class MyCustomSettingsUIElementsRegister
{
    [SettingsProvider]
    public static SettingsProvider CreateMyCustomSettingsProvider()
    {
        //第一个参数是Setting窗口中的路径
        //第二个参数是此设置的范围:它仅出现在Project Setting窗口中。
        var provider = new SettingsProvider("Project/MyCustomUIElementSettings", SettingsScope.Project)
        {
            label = "Custom UI Elements",
            //当用户单击Setting窗口中的Setting菜单项时,将调用activateHandler。
            activateHandler = (searchContext, rootElement) =>
            {
                var settings = MyCustomSettings.GetSerializedSettings();
                //rootElement是一个VisualElement。 如果向其添加任何子项,则不会调用OnGUI函数,
                //因为SettingsProvider使用UIElements绘图框架。
                var styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Editor/settings_ui.uss");
                rootElement.styleSheets.Add(styleSheet);
                var title = new Label()
                {
                    text = "Custom UI Elements"
                };
                title.AddToClassList("title");
                rootElement.Add(title);
                var properties = new VisualElement()
                {
                    style =
                    {
                        flexDirection = FlexDirection.Column
                    }
                };
                properties.AddToClassList("property-list");
                rootElement.Add(properties);
                var tf = new TextField()
                {
                    value = settings.FindProperty("m_SomeString").stringValue
                };
                tf.AddToClassList("property-value");
                properties.Add(tf);
            },

            keywords = new HashSet<string>(new[] { "Number", "Some String" })
        };
        return provider;
    }
}

unity 自定义enum unity 自定义快捷键_菜单项_09

using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor;
using System.IO;

//创建新类型Setting Asset
class MyCustomSettings : ScriptableObject
{
    public const string k_MyCustomSettingsPath = "Assets/Editor/MyCustomSettings.asset";
    [SerializeField] private int m_Number;
    [SerializeField] private string m_SomeString;
    internal static MyCustomSettings GetOrCreateSetting()
    {
        var settings = AssetDatabase.LoadAssetAtPath<MyCustomSettings>(k_MyCustomSettingsPath);
        if (settings == null)
        {
            settings = ScriptableObject.CreateInstance<MyCustomSettings>();
            settings.m_Number = 42;
            settings.m_SomeString = "The answer to the universe";
            AssetDatabase.CreateAsset(settings, k_MyCustomSettingsPath);
            AssetDatabase.SaveAssets();
        }
        return settings;
    }
    internal static SerializedObject GetSerializedSettings()
    {
        return new SerializedObject(GetOrCreateSetting());
    }
}
//通过从SettingsProvider派生类来创建MyCustomSettingsProvider
class MyCustomSettingsProvider : SettingsProvider
{
    private SerializedObject m_CustomSettings;
    class Styles
    {
        public static GUIContent number = new GUIContent("My Number");
        public static GUIContent someString = new GUIContent("Some string");
    }
    const string k_MyCustomSettingsPath = "Assets/Editor/MyCustomSettings.asset";
    public MyCustomSettingsProvider(string path, SettingsScope scope = SettingsScope.User) : base(path, scope) { }
    public static bool IsSettingsAvailable()
    {
        return File.Exists(k_MyCustomSettingsPath);
    }
    public override void OnActivate(string searchContext, VisualElement rootElement)
    {
        //当用户单击Setting窗口中的MyCustom菜单项时,将调用此函数。
        m_CustomSettings = MyCustomSettings.GetSerializedSettings();
    }
    public override void OnGUI(string searchContext)
    {
        //使用IMGUI显示UI
        EditorGUILayout.PropertyField(m_CustomSettings.FindProperty("m_Number"), Styles.number);
        EditorGUILayout.PropertyField(m_CustomSettings.FindProperty("m_SomeString"), Styles.someString);
    }

    //注册SettingsProvider
    [SettingsProvider]
    public static SettingsProvider CreateMyCustomSettingsProvider()
    {
        if (IsSettingsAvailable())
        {
            var provider = new MyCustomSettingsProvider("Project/MyCustomSettignsProvider", SettingsScope.Project);
            //自动从样式中提取所有关键字
            provider.keywords = GetSearchKeywordsFromGUIContentProperties<Styles>();
            return provider;
        }
        //Settings Asset不存在; 无需在Settings窗口中显示任何内容。
        return null;
    }
}

unity 自定义enum unity 自定义快捷键_函数定义_10


  (2) Properties

activateHandler:重写SettingsProvider.OnActivate。
函数定义:public Action<string,VisualElement> activateHandler;
deactivateHandler:重写SettingsProvider.OnDeactivate。
函数定义:public Action deactivateHandler;
footerBarGuiHandler:重写SettingsProvider.OnFooterBarGUI。
函数定义:public Action footerBarGuiHandler;
guiHandler:重写SettingsProvider.OnGUI。
函数定义:public Action<string> guiHandler;
hasSearchInterestHandler:重写SettingsProvider.HasSearchInterest。
函数定义:public Func<string,bool> hasSearchInterestHandler;
inspectorUpdateHandler:重写SettingsProvider.OnInspectorUpdate。
函数定义:public Action inspectorUpdateHandler;
keywords:获取或设置关键字列表,以与用户搜索的内容进行比较。 当用户在Settings窗口的搜索框中输入值时,SettingsProvider.HasSearchInterest尝试将那些关键字与此列表匹配。
函数定义:public IEnumerable<string> keywords;
label:获取或设置SettingsProvider在Settings窗口中显示的显示名称。 如果未设置,则Settings窗口将使用SettingsProvider.settingsPath的最后一个标记。
函数定义:public string label;
代码示例:
using UnityEditor;

class SettingsProviderExamples
{
    [SettingsProvider]
    static SettingsProvider CreateVariousSettingsProviders1()
    {
        //新的Project设置菜单显示在其自己的根部分(MyOwnSection)中,但未分组在所有核心设置下。
        var p = new SettingsProvider("MyOwnSection/MySettings", SettingsScope.Project);
        //here p.label = "MySettings"
        return p;
    }
    [SettingsProvider]
    static SettingsProvider CreateVariousSettingsProviders2()
    {
        //第一个参数是用于将Settings放置在树形视图中的唯一ID。
        //如果指定了label,则它将成为SettingsProvider的显示名称。
        var p2 = new SettingsProvider("MyOwnSection/MySettingsOfDoom", SettingsScope.Project)
        {
            label = "A more proper Settings Name"
        };
        return p2;
    }

    [SettingsProvider]
    static SettingsProvider CreateVariousSettingsProviders3()
    {
        //第二个参数是SettingsProvider的范围。 它确定此SettingsProvider是否出现在
        //Settings窗口(用于通过SettingsScope.Project指定的项目设置)
        //或是否出现在Preferences窗口中(通过SettingsScope.User指定时)
        var p3 = new SettingsProvider("Preferences/Multi touch", SettingsScope.User);
        return p3;
    }
}

unity 自定义enum unity 自定义快捷键_函数定义_11

scope:获取SettingsProvider的范围。 确定SettingsProvider是出现在Preferences窗口(SettingsScope.User)还是Settings窗口(SettingsScope.Project)中。
函数定义:public SettingsScope scope;
settingsPath:获取用于将SettingsProvider放置在Settings窗口的树视图中的路径。 该路径在所有其他设置路径中应该是唯一的,并且应使用“ /”作为其分隔符。
函数定义:public string settingsPath;
titleBarGuiHandler:重写SettingsProvider.OnTitleBarGUI。
函数定义:public Action titleBarGuiHandler;

  (3) Constructors

SettingsProvider:创建一个新的SettingsProvider。
函数定义:public SettingsProvider(string path, SettingsScope scopes, IEnumerable<string> keywords);
函数参数:
1.path:Settings窗口中设置的路径。 使用“ /”作为分隔符。 如果没有提供label,则最后一个字符串将设置为label。
2.scope:设置范围。 确定设置显示的位置:在Settings或Preferences窗口中。
3.keywords:与用户搜索内容进行比较的关键字列表。 当用户在Settings窗口的搜索框中输入值时,SettingsProvider.HasSearchInterest尝试将那些关键字与此列表匹配。

  (4) Public Methods

HasSearchInterest:检查当用户在Settings窗口搜索框中键入内容时,是否应显示SettingsProvider。 SettingsProvider尝试将搜索词(甚至部分匹配)与任何SettingsProvider.keywords匹配。 搜索不区分大小写。
函数定义:public bool HasSearchInterest(string searchContext);
函数参数:
1.searchContext:用户在Settings窗口的搜索框搜索词。
函数返回值:
1.bool:如果SettingsProvider匹配搜索词并且应该显示,则为True。
OnActivate:使用此功能可为用户单击Settings窗口中的菜单项提供一个处理程序。 你可以用此函数获取菜单项asset或设置UIElements UI。
函数定义:public void OnActivate(string searchContext, UIElements.VisualElement rootElement);
函数参数:
1.searchContext:在“设置”窗口上的搜索框中搜索上下文。
2.rootElement:UIElements树的根节点。 如果添加到此根目录,则SettingsProvider使用UIElements而不是调用SettingsProvider.OnGUI来构建UI。 如果不添加到此VisualElement,则必须使用IMGUI来构建UI。
代码示例1:
using UnityEditor;
using UnityEngine.UIElements;
using UnityEngine;
class MyCustomSettings : ScriptableObject
{
    public const string k_MyCustomSettingsPath = "Assets/Editor/MyCustomSettings.asset";
    [SerializeField] private int m_Number;
    [SerializeField] private string m_SomeString;
    internal static MyCustomSettings GetOrCreateSetting()
    {
        var settings = AssetDatabase.LoadAssetAtPath<MyCustomSettings>(k_MyCustomSettingsPath);
        if (settings == null)
        {
            settings = ScriptableObject.CreateInstance<MyCustomSettings>();
            settings.m_Number = 42;
            settings.m_SomeString = "The answer to the universe";
            AssetDatabase.CreateAsset(settings, k_MyCustomSettingsPath);
            AssetDatabase.SaveAssets();
        }
        return settings;
    }
}
class SimpleIMGUISettingsProvider : SettingsProvider
{
    SerializedObject m_Settings;
    public SimpleIMGUISettingsProvider(string path, SettingsScope scope = SettingsScope.User) : base(path, scope) { }
    public override void OnActivate(string searchContext, VisualElement rootElement)
    {
        //当用户单击“设置”窗口中的MyCustom元素时调用
        m_Settings = new SerializedObject(MyCustomSettings.GetOrCreateSetting());
    }
    public override void OnDeactivate()
    {
        //用户选择了另一个设置或关闭了“设置”窗口
        m_Settings = null;
    }
    public override void OnFooterBarGUI()
    {
        EditorGUILayout.LabelField("FooterBar");
    }
    public override void OnTitleBarGUI()
    {
        //此按钮显示在当前选定的SettingsProvider的标题之后:
        if(GUILayout.Button("Help", EditorStyles.miniButton))
        {
            Debug.Log("You are on your own");
        }
    }
    public override void OnGUI(string searchContext)
    {
        //使用IMGUI显示UI:
        EditorGUILayout.PropertyField(m_Settings.FindProperty("m_Number"), new GUIContent("MyNumber"));
        EditorGUILayout.PropertyField(m_Settings.FindProperty("m_SomeString"), new GUIContent("Some string"));
    }
    //注册SettingsProvider
    [SettingsProvider]
    public static SettingsProvider CreateMyCustomSettingsProvider()
    {
        //Editor菜单下的Preferences/MyCustomSettingsProvider菜单项
        SimpleIMGUISettingsProvider provider = new SimpleIMGUISettingsProvider("Preferences/MyCustomSettingsProvider", SettingsScope.User);
        provider.inspectorUpdateHandler += () =>
        {
            //当从Inspector更新PresetManager时,检查是否需要更新 Preset Settings View
            if(provider.m_Settings != null && provider.m_Settings.UpdateIfRequiredOrScript())
            {
                provider.Repaint();
            }
        };
        return provider;
    }
}
代码示例2:本示例说明如何基于UIElements构建SettingsProvider:需要将任何子级在OnActivate函数中添加传递给rootElement。
using UnityEditor;
using UnityEngine.UIElements;
using UnityEngine;
class MyCustomSettings:ScriptableObject
{
    public const string k_MyCustomSettingsPath = "Assets/Editor/MyCustomSettings.asset";
    [SerializeField] private int m_Number;
    [SerializeField] private string m_SomeString;
    internal static MyCustomSettings GetOrCreateSetting()
    {
        var settings = AssetDatabase.LoadAssetAtPath<MyCustomSettings>(k_MyCustomSettingsPath);
        if(settings == null)
        {
            settings = ScriptableObject.CreateInstance<MyCustomSettings>();
            settings.m_Number = 42;
            settings.m_SomeString = "The answer to the universe";
            AssetDatabase.CreateAsset(settings, k_MyCustomSettingsPath);
            AssetDatabase.SaveAssets();
        }
        return settings;
    }
}
class SimpleIMGUISettingsProvider:SettingsProvider
{
    SerializedObject m_Settings;
    public SimpleIMGUISettingsProvider(string path, SettingsScope scope = SettingsScope.User):base(path, scope) { }
    public override void OnActivate(string searchContext, VisualElement rootElement)
    {
        //当用户单击“设置”窗口中的MyCustom元素时调用
        m_Settings = new SerializedObject(MyCustomSettings.GetOrCreateSetting());
        //rootElement是一个VisualElement。 如果向其添加任何子级,则说明您正在使用UIElements来构建SettingsProvider
        var styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Editor/settings_ui.uss");
        rootElement.styleSheets.Add(styleSheet);
        var title = new Label()
        {
            text = "Custom UI Elements"
        };
        title.AddToClassList("title");
        rootElement.Add(title);
        var tf = new TextField()
        {
            value = m_Settings.FindProperty("m_SomeString").stringValue
        };
        tf.AddToClassList("property-value");
        rootElement.Add(tf);

    }

    public override void OnGUI(string searchContext)
    {
        //因为UIElements正在绘制UI,所以永远不会调用此函数。
    }
    //注册SettingsProvider
    [SettingsProvider]
    public static SettingsProvider CreateMyCustomSettingsProvider()
    {
        //Preferences/MyCustomSettingsProvider菜单项
        SimpleIMGUISettingsProvider provider = new SimpleIMGUISettingsProvider("Preferences/MyCustomSettingsProvider", SettingsScope.User);
        return provider;
    }
}

unity 自定义enum unity 自定义快捷键_ide_12


unity 自定义enum unity 自定义快捷键_函数定义_13

OnDeactivate:使用此功能可为用户单击其他设置或“设置”窗口关闭时实现处理程序。
函数定义:public void OnDeactivate();
代码示例:见OnActivate代码示例1
OnFooterBarGUI:使用此功能可以使用IMGUI为SettingsProvider绘制页脚。
函数定义:public void OnFooterBarGUI();
代码示例:见OnActivate代码示例1
OnGUI:使用此功能可基于IMGUI绘制UI。假设您尚未将任何子级在OnActivate函数中添加传递给rootElement。
函数定义:public void OnGUI(string searchContext);
函数参数:
1.searchContext:“设置”窗口搜索时的匹配关键字。 用于显示或隐藏相关属性。
代码示例:见OnActivate代码示例1
OnInspectorUpdate:以每秒10帧的速度调用OnInspectorUpdate,以使检查器有机会进行更新。 有关更多详细信息,参见EditorWindow.OnInspectorUpdate。
函数定义:public void OnInspectorUpdate();
代码示例:
using UnityEditor;
using UnityEngine.UIElements;
using UnityEngine;
class MyCustomSettings : ScriptableObject
{
    public const string k_MyCustomSettingsPath = "Assets/Editor/MyCustomSettings.asset";
    [SerializeField] private int m_Number;
    [SerializeField] private string m_SomeString;
    internal static MyCustomSettings GetOrCreateSetting()
    {
        var settings = AssetDatabase.LoadAssetAtPath<MyCustomSettings>(k_MyCustomSettingsPath);
        if (settings == null)
        {
            settings = ScriptableObject.CreateInstance<MyCustomSettings>();
            settings.m_Number = 42;
            settings.m_SomeString = "The answer to the universe";
            AssetDatabase.CreateAsset(settings, k_MyCustomSettingsPath);
            AssetDatabase.SaveAssets();
        }
        return settings;
    }
}
class SimpleIMGUISettingsProvider : SettingsProvider
{
    SerializedObject m_Settings;
    public SimpleIMGUISettingsProvider(string path, SettingsScope scope = SettingsScope.User) : base(path, scope) { }
    public override void OnActivate(string searchContext, VisualElement rootElement)
    {
        //当用户单击“设置”窗口中的MyCustom元素时调用
        m_Settings = new SerializedObject(MyCustomSettings.GetOrCreateSetting());
    }
    public override void OnDeactivate()
    {
        //用户选择了另一个设置或关闭了“设置”窗口
        m_Settings = null;
    }
    public override void OnFooterBarGUI()
    {
        EditorGUILayout.LabelField("FooterBar");
    }
    public override void OnGUI(string searchContext)
    {
        //使用IMGUI显示UI:
        EditorGUILayout.PropertyField(m_Settings.FindProperty("m_Number"), new GUIContent("MyNumber"));
        EditorGUILayout.PropertyField(m_Settings.FindProperty("m_SomeString"), new GUIContent("Some string"));
    }
    //注册SettingsProvider
    [SettingsProvider]
    public static SettingsProvider CreateMyCustomSettingsProvider()
    {
        //Editor菜单下的Preferences/MyCustomSettingsProvider菜单项
        SimpleIMGUISettingsProvider provider = new SimpleIMGUISettingsProvider("Preferences/MyCustomSettingsProvider", SettingsScope.User);
        provider.inspectorUpdateHandler += () =>
        {
            //当从Inspector更新PresetManager时,检查是否需要更新 Preset Settings View
            //若MyCustomSettings.asset的值在Inspector中被修改时,对应的MyCustomSettingsProvider也会同步刷新
            if(provider.m_Settings != null && provider.m_Settings.UpdateIfRequiredOrScript())
            {
                provider.Repaint();
            }
        };
        return provider;
    }
}
OnTitleBarGUI:使用此功能可以覆盖使用IMGUI绘制SettingsProvider的标题。 这使您可以在标题旁边添加自定义UI(例如工具栏按钮)。 AssetSettingsProvider使用此机制来显示“添加到预设”和“帮助”按钮。
函数定义:public void OnTitleBarGUI();
代码示例:见OnActivate代码示例1
Repaint:请求SettingsWindow进行重画。
函数定义:public void Repaint();

  (4) Public Methods

GetSearchKeywordsFromGUIContentProperties:从特定类型的所有公共静态成员中提取搜索关键字。
函数定义:public static IEnumerable<string> GetSearchKeywordsFromGUIContentProperties();
函数返回值:
1IEnumerable<string>:返回从静态GUIContent提取的关键字列表。
代码示例:
using UnityEditor;
using UnityEngine.UIElements;
using UnityEngine;
class MyCustomSettings : ScriptableObject
{
    public const string k_MyCustomSettingsPath = "Assets/Editor/MyCustomSettings.asset";
    [SerializeField] private int m_Number;
    [SerializeField] private string m_SomeString;
    internal static MyCustomSettings GetOrCreateSetting()
    {
        var settings = AssetDatabase.LoadAssetAtPath<MyCustomSettings>(k_MyCustomSettingsPath);
        if (settings == null)
        {
            settings = ScriptableObject.CreateInstance<MyCustomSettings>();
            settings.m_Number = 42;
            settings.m_SomeString = "The answer to the universe";
            AssetDatabase.CreateAsset(settings, k_MyCustomSettingsPath);
            AssetDatabase.SaveAssets();
        }
        return settings;
    }
    internal static SerializedObject GetSerializedSettings()
    {
        return new SerializedObject(GetOrCreateSetting());
    }
}
class SimpleIMGUISettingsProvider : SettingsProvider
{
    public SimpleIMGUISettingsProvider(string path, SettingsScope scope = SettingsScope.User) : base(path, scope) { }
    [SettingsProvider]
    public static SettingsProvider CreateFromFilePath()
    {
        //从文件路径创建AssetSettingsProvider:
        var provider = AssetSettingsProvider.CreateProviderFromAssetPath("Project/AssetSettings/FromFile", MyCustomSettings.k_MyCustomSettingsPath);
        //在特定路径下从序列化对象的属性中注册关键字
        provider.keywords = SettingsProvider.GetSearchKeywordsFromPath(MyCustomSettings.k_MyCustomSettingsPath);
        //输出:Script Number Some String
        //foreach (string key in provider.keywords)
        //{
        //    Debug.LogError(key);
        //}
        return provider;
    }
    [SettingsProvider]
    public static SettingsProvider CreateFromSettingsObject()
    {
        //从设置对象(UnityEngine.Object)创建AssetSettingsProvider:
        var settingsObj = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(MyCustomSettings.k_MyCustomSettingsPath);
        var provider = AssetSettingsProvider.CreateProviderFromObject("Project/AssetSettings/FromObject", settingsObj);
        //从settingsObj属性注册关键字
        provider.keywords = SettingsProvider.GetSearchKeywordsFromSerializedObject(new SerializedObject(settingsObj));
        //输出:Script Number Some String
        //foreach (string key in provider.keywords)
        //{
        //    Debug.LogError(key);
        //}
        return provider;
    }
    class Styles
    {
        public static GUIContent number = new GUIContent("My Number");
        public static GUIContent someString = new GUIContent("Some string");
    }
    [SettingsProvider]
    public static SettingsProvider CreateFromSettingsFromFunctor()
    {
        //从必须返回UnityEngine.Object的函数创建一个AssetSettingsProvider:
        var provider = new AssetSettingsProvider("Project/AssetSettings/FromFunctor", () => Editor.CreateEditor(AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(MyCustomSettings.k_MyCustomSettingsPath)));
        //在Styles类中从静态GUIContent注册关键字
        provider.keywords = SettingsProvider.GetSearchKeywordsFromGUIContentProperties<Styles>();
        //输出:Number Some String
        //foreach (string key in provider.keywords)
        //{
        //    Debug.LogError(key);
        //}
        return provider;
    }
}

unity 自定义enum unity 自定义快捷键_函数定义_14

GetSearchKeywordsFromPath:从资产的序列化属性中的特定路径中提取搜索关键字。
函数定义:public static IEnumerable<string> GetSearchKeywordsFromPath(string path);
函数参数:path:资产在磁盘上的路径。
函数返回值:
IEnumerable<string>:返回关键字列表
代码示例:见GetSearchKeywordsFromGUIContentProperties
GetSearchKeywordsFromSerializedObject:从SerializedObject的序列化属性中提取搜索关键字。
函数定义:public static IEnumerable<string> GetSearchKeywordsFromSerializedObject(SerializedObject serializedObject);
函数参数:serializedObject	Object to extract properties from.

  参考资料
  1.MenuItem:https://docs.unity3d.com/ScriptReference/MenuItem.html
  2.ScriptableObject:https://docs.unity3d.com/2018.3/Documentation/ScriptReference/ScriptableObject.html
  3.SettingsProvider:https://docs.unity3d.com/2019.3/Documentation/ScriptReference/SettingsProvider.html