• 自定义ProjectSettings设置项


    基于ScriptableObject资源和SettingsProvider特性方式实现

    1.实现ScriptableObject数据设计

    1. /// <summary>
    2. /// 用于存储我们的设置配置
    3. /// </summary>
    4. public class EditorLearnSettings : ScriptableObject
    5. {
    6. /// <summary>
    7. /// 用于我们设置的保存位置
    8. /// </summary>
    9. private const string SettingsFile= "Assets/Settings/EditorLearnSetting.asset";
    10. #region 此处可以存储我们自定义的配置信息
    11. /// <summary>
    12. /// 模拟我们的配置
    13. /// </summary>
    14. public int m_ConfigVersionCode = 1;
    15. #endregion
    16. }

    2.提供配置文件内容的全局实例方法 

    在我们的EditorLearnSettings类提供以下方法,为我们提供全局配置信息。

    1. /// <summary>
    2. /// 这里提供一个配置对象
    3. /// </summary>
    4. /// <returns></returns>
    5. public static EditorLearnSettings GetOrCreateSettings()
    6. {
    7. var settings = AssetDatabase.LoadAssetAtPath<EditorLearnSettings>(SettingsFile);
    8. if (settings == null)
    9. {
    10. settings = ScriptableObject.CreateInstance<EditorLearnSettings>();
    11. settings.m_ConfigVersionCode = 0;
    12. if (!Directory.Exists(Path.GetDirectoryName(SettingsFile)))
    13. {
    14. Directory.CreateDirectory(Path.GetDirectoryName(SettingsFile));
    15. }
    16. AssetDatabase.CreateAsset(settings, SettingsFile);
    17. AssetDatabase.SaveAssets();
    18. }
    19. return settings;
    20. }
    21. /// <summary>
    22. /// 提供一个SerializedObject的对象
    23. /// </summary>
    24. /// <returns></returns>
    25. public static SerializedObject GetSerializedSettings()
    26. {
    27. return new SerializedObject(GetOrCreateSettings());
    28. }
    • 当资源配置被创建出来我们可以直接进行配置,如果不想通过资源配置文件配置,可以为其制定一个CustomEditor。
    1. [CustomEditor(typeof(EditorLearnSettings))]
    2. public class EditorLearnSettingsView:Editor
    3. {
    4. protected override void OnHeaderGUI()
    5. {
    6. GUILayout.Label("请从Project Settings配置");
    7. }
    8. public override void OnInspectorGUI() { }
    9. }

    3.编写一个提供SettingsProvider数据的静态方法。

    我们继续在EditorLearnSettings类提供以下方法。

    1. /// <summary>
    2. /// 这里主要是制定我们的Settings路径
    3. /// </summary>
    4. private const string ProjectSettingPtah = "Project/编辑器学习";
    5. /// <summary>
    6. /// 将我们的Setting提供给Unity
    7. /// </summary>
    8. /// <returns></returns>
    9. [SettingsProvider]
    10. public static SettingsProvider CreateEditorLearnSettingsProvider()
    11. {
    12. ///创建一个SettingsProvider
    13. var provider = new SettingsProvider(ProjectSettingPtah, SettingsScope.Project)
    14. {
    15. guiHandler = (searchContext) =>
    16. {
    17. ///searchContext:提供用户搜索的信息
    18. ///这里是一个gui的处理行为
    19. var settings = EditorLearnSettings.GetSerializedSettings();
    20. EditorGUILayout.PropertyField(settings.FindProperty("m_ConfigVersionCode"), new GUIContent("版本码:"));
    21. settings.ApplyModifiedPropertiesWithoutUndo();
    22. },
    23. // 用于搜索的关键字,在Project 可以搜索对应的配置
    24. keywords = new HashSet<string>(new[] { "Learn", "KTGame" })
    25. };
    26. return provider;
    27. }

     4.到此我们就可以在Project Setting看见我们自定义的配置模块了。

    5.完整代码

    1. using System.Collections.Generic;
    2. using UnityEditor;
    3. using UnityEngine;
    4. using System.IO;
    5. [CustomEditor(typeof(EditorLearnSettings))]
    6. public class EditorLearnSettingsView:Editor
    7. {
    8. protected override void OnHeaderGUI()
    9. {
    10. GUILayout.Label("请从Project Settings配置");
    11. }
    12. public override void OnInspectorGUI() { }
    13. }
    14. /// <summary>
    15. /// 用于存储我们的设置配置
    16. /// </summary>
    17. public class EditorLearnSettings : ScriptableObject
    18. {
    19. /// <summary>
    20. /// 用于我们设置的保存位置
    21. /// </summary>
    22. private const string SettingsFile= "Assets/Settings/EditorLearnSetting.asset";
    23. #region 此处可以存储我们自定义的配置信息
    24. /// <summary>
    25. /// 模拟我们的配置
    26. /// </summary>
    27. public int m_ConfigVersionCode = 1;
    28. #endregion
    29. /// <summary>
    30. /// 这里提供一个全局的设置获取方式
    31. /// </summary>
    32. /// <returns></returns>
    33. public static EditorLearnSettings GetOrCreateSettings()
    34. {
    35. var settings = AssetDatabase.LoadAssetAtPath<EditorLearnSettings>(SettingsFile);
    36. if (settings == null)
    37. {
    38. settings = ScriptableObject.CreateInstance<EditorLearnSettings>();
    39. settings.m_ConfigVersionCode = 0;
    40. if (!Directory.Exists(Path.GetDirectoryName(SettingsFile)))
    41. {
    42. Directory.CreateDirectory(Path.GetDirectoryName(SettingsFile));
    43. }
    44. AssetDatabase.CreateAsset(settings, SettingsFile);
    45. AssetDatabase.SaveAssets();
    46. }
    47. return settings;
    48. }
    49. /// <summary>
    50. /// 提供一个SerializedObject的获取
    51. /// </summary>
    52. /// <returns></returns>
    53. public static SerializedObject GetSerializedSettings()
    54. {
    55. return new SerializedObject(GetOrCreateSettings());
    56. }
    57. /// <summary>
    58. /// 这里主要是制定我们的Settings路径
    59. /// </summary>
    60. private const string ProjectSettingPtah = "Project/编辑器学习";
    61. /// <summary>
    62. /// 将我们的Setting提供给Unity
    63. /// </summary>
    64. /// <returns></returns>
    65. [SettingsProvider]
    66. public static SettingsProvider CreateEditorLearnSettingsProvider()
    67. {
    68. ///创建一个SettingsProvider
    69. var provider = new SettingsProvider(ProjectSettingPtah, SettingsScope.Project)
    70. {
    71. guiHandler = (searchContext) =>
    72. {
    73. ///searchContext:提供用户搜索的信息
    74. ///这里是一个gui的处理行为
    75. var settings = EditorLearnSettings.GetSerializedSettings();
    76. EditorGUILayout.PropertyField(settings.FindProperty("m_ConfigVersionCode"), new GUIContent("版本码:"));
    77. settings.ApplyModifiedPropertiesWithoutUndo();
    78. },
    79. // 用于搜索的关键字,在Project 可以搜索对应的配置
    80. keywords = new HashSet<string>(new[] { "Learn", "KTGame" })
    81. };
    82. return provider;
    83. }
    84. }

    基于继承SettingsProvider的实现方式。

    1.同样需要一个配置文件。

    配置文件我们直接使用上面的文件。

    1. /// <summary>
    2. /// 用于存储我们的设置配置
    3. /// </summary>
    4. public class EditorLearnSettings : ScriptableObject
    5. {
    6. /// <summary>
    7. /// 用于我们设置的保存位置
    8. /// </summary>
    9. private const string SettingsFile= "Assets/Settings/EditorLearnSetting.asset";
    10. #region 此处可以存储我们自定义的配置信息
    11. /// <summary>
    12. /// 模拟我们的配置
    13. /// </summary>
    14. public int m_ConfigVersionCode = 1;
    15. #endregion
    16. /// <summary>
    17. /// 这里提供一个全局的设置获取方式
    18. /// </summary>
    19. /// <returns></returns>
    20. public static EditorLearnSettings GetOrCreateSettings()
    21. {
    22. var settings = AssetDatabase.LoadAssetAtPath<EditorLearnSettings>(SettingsFile);
    23. if (settings == null)
    24. {
    25. settings = ScriptableObject.CreateInstance<EditorLearnSettings>();
    26. settings.m_ConfigVersionCode = 0;
    27. if (!Directory.Exists(Path.GetDirectoryName(SettingsFile)))
    28. {
    29. Directory.CreateDirectory(Path.GetDirectoryName(SettingsFile));
    30. }
    31. AssetDatabase.CreateAsset(settings, SettingsFile);
    32. AssetDatabase.SaveAssets();
    33. }
    34. return settings;
    35. }
    36. /// <summary>
    37. /// 提供一个SerializedObject的获取
    38. /// </summary>
    39. /// <returns></returns>
    40. public static SerializedObject GetSerializedSettings()
    41. {
    42. return new SerializedObject(GetOrCreateSettings());
    43. }
    44. }

    2.继承 SettingsProvider

    首先我们创建EditorLearnSettingsProvider类并继承SettingsProvider

    public class EditorLearnSettingsProvider: SettingsProvider{}

    实现SettingsProvider构造函数。

    public EditorLearnSettingsProvider(string path, SettingsScope scope) : base(path, scope) { }

    重写OnGUI和OnActivate

    1. /// <summary>
    2. /// 当模块被激活时被调用
    3. /// </summary>
    4. /// <param name="searchContext">用户搜索的内容</param>
    5. /// <param name="rootElement">UIElements根节点。如果添加到此,则 SettingsProvider 使用 UIElements 而不是调用 SettingsProvider.OnGUI 来构建 UI。如果不添加到此 VisualElement,则必须使用 IMGUI 来构建 UI。</param>
    6. public override void OnActivate(string searchContext, VisualElement rootElement)
    7. {
    8. serializedObject = EditorLearnSettings.GetSerializedSettings();
    9. }
    10. public override void OnGUI(string searchContext)
    11. {
    12. EditorGUILayout.PropertyField(serializedObject.FindProperty("m_ConfigVersionCode"), new GUIContent("版本码:"));
    13. }

    3.通过SettingsProvider方法特性注册到SettingsProvider中

    1. [SettingsProvider]
    2. public static SettingsProvider CreateMyCustomSettingsProvider()
    3. {
    4. var provider = new EditorLearnSettingsProvider(ProjectSettingPtah, SettingsScope.Project);
    5. provider.keywords = new[] { "Learn", "KTGame" };
    6. return provider;
    7. }

    4.完整代码

    1. using UnityEditor;
    2. using UnityEngine;
    3. using System.IO;
    4. using UnityEngine.UIElements;
    5. [CustomEditor(typeof(EditorLearnSettings))]
    6. public class EditorLearnSettingsView:Editor
    7. {
    8. protected override void OnHeaderGUI()
    9. {
    10. GUILayout.Label("请从Project Settings配置");
    11. }
    12. public override void OnInspectorGUI() { }
    13. }
    14. /// <summary>
    15. /// 用于存储我们的设置配置
    16. /// </summary>
    17. public class EditorLearnSettings : ScriptableObject
    18. {
    19. /// <summary>
    20. /// 用于我们设置的保存位置
    21. /// </summary>
    22. private const string SettingsFile= "Assets/Settings/EditorLearnSetting.asset";
    23. #region 此处可以存储我们自定义的配置信息
    24. /// <summary>
    25. /// 模拟我们的配置
    26. /// </summary>
    27. public int m_ConfigVersionCode = 1;
    28. #endregion
    29. /// <summary>
    30. /// 这里提供一个全局的设置获取方式
    31. /// </summary>
    32. /// <returns></returns>
    33. public static EditorLearnSettings GetOrCreateSettings()
    34. {
    35. var settings = AssetDatabase.LoadAssetAtPath<EditorLearnSettings>(SettingsFile);
    36. if (settings == null)
    37. {
    38. settings = ScriptableObject.CreateInstance<EditorLearnSettings>();
    39. settings.m_ConfigVersionCode = 0;
    40. if (!Directory.Exists(Path.GetDirectoryName(SettingsFile)))
    41. {
    42. Directory.CreateDirectory(Path.GetDirectoryName(SettingsFile));
    43. }
    44. AssetDatabase.CreateAsset(settings, SettingsFile);
    45. AssetDatabase.SaveAssets();
    46. }
    47. return settings;
    48. }
    49. /// <summary>
    50. /// 提供一个SerializedObject的获取
    51. /// </summary>
    52. /// <returns></returns>
    53. public static SerializedObject GetSerializedSettings()
    54. {
    55. return new SerializedObject(GetOrCreateSettings());
    56. }
    57. }
    58. public class EditorLearnSettingsProvider: SettingsProvider
    59. {
    60. private const string ProjectSettingPtah = "Project/编辑器学习";
    61. public EditorLearnSettingsProvider(string path, SettingsScope scope) : base(path, scope) { }
    62. private SerializedObject serializedObject;
    63. /// <summary>
    64. /// 当模块被激活时被调用
    65. /// </summary>
    66. /// <param name="searchContext">用户搜索的内容</param>
    67. /// <param name="rootElement">UIElements根节点。如果添加到此,则 SettingsProvider 使用 UIElements 而不是调用 SettingsProvider.OnGUI 来构建 UI。如果不添加到此 VisualElement,则必须使用 IMGUI 来构建 UI。</param>
    68. public override void OnActivate(string searchContext, VisualElement rootElement)
    69. {
    70. serializedObject = EditorLearnSettings.GetSerializedSettings();
    71. }
    72. public override void OnGUI(string searchContext)
    73. {
    74. EditorGUILayout.PropertyField(serializedObject.FindProperty("m_ConfigVersionCode"), new GUIContent("版本码:"));
    75. }
    76. [SettingsProvider]
    77. public static SettingsProvider CreateMyCustomSettingsProvider()
    78. {
    79. var provider = new EditorLearnSettingsProvider(ProjectSettingPtah, SettingsScope.Project);
    80. provider.keywords = new[] { "Learn", "KTGame" };
    81. return provider;
    82. }
    83. }

    总结

    • SettingsScope共有两项,User显示在Preferences 窗口;Project显示在Project Settings窗口。
    • 这里我们使用的是ScriptableObject方式对配置进行存储,我们也可以使用其它的方式存储在非工程里或者存在ProjectSettings文件夹里。
    • 我们存储的配置目标尽可能的保证全局的唯一性。
    • 关于Project Settings配置模块和Preferences 配置我们还是最好进行一个统一的管理。
    • AssetDatabase.CreateAsset创建资源时要保证路径有效。
    • 此主题所有代码都是编辑器代码应该放在Editor下。
    • 如果我们需要提交多个配置模块可以使用SettingsProviderGroup,你的方法应该提供一个SettingsProvider[]
  • 相关阅读:
    【SA8295P 源码分析 (三)】130 - GMSL2 协议分析 之 I2C/UART 双向控制通道原理分析
    算法---相等行列对
    JavaScript 编写排序算法:冒泡排序、选择排序、插入排序
    智慧社区的魔力:数据可视化的引领之力
    16/32/64位操作系统下,各种变量类型分别占多少字节
    Tomcat报BAD packet signature 18245错误的原因
    IO Watch:用 Arduino UNO 制造的可编程手表
    隐私计算+区块链原生融合之后平台开放、提升性能,蚂蚁链隐私协作平台FAIR重磅架构升级
    C语言——程序解构说明
    【21天学习挑战赛】算法——算法概述
  • 原文地址:https://blog.csdn.net/l100142548/article/details/125406990