先看一下最终效果
这是ProjectSetting窗口效果,我实际存储了TBCEditorSetting.asset这个资源的GUID,这里只是重写了GUI
数据存储在ProjectSettings/TBCFrameworkSettings.asset
这里要注意的是这个asset文件不在Assets文件夹下,所以不能使用AssetDatabase来加载,需要使用InternalEditorUtility的LoadSerializedFileAndForget与SaveToSerializedFileAndForget接口进行加载与创建/保存
另一个注意点是继承ScriptableObject的类的文件夹要与类名保存一致,和Momobehaivor脚本一样
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.UIElements;
namespace TBC.Editor
{
class TBCProjectSettings: ScriptableObject
{
[System.Serializable]
class SerializeProperty
{
public string Key;
public string Value;
}
//serialize cache
[SerializeField]
List
//runtime cache
Dictionary
//save path
const string s_AssetPath = "ProjectSettings/TBCFrameworkSettings.asset";
static TBCProjectSettings s_Instance;
static TBCProjectSettings Instance
{
get
{
if (s_Instance == null)
{
var objs = InternalEditorUtility.LoadSerializedFileAndForget(s_AssetPath);
if (objs != null && objs.Length > 0)
{
s_Instance = objs[0] as TBCProjectSettings;
Debug.LogError(objs[0]);
}
if (s_Instance == null)
{
s_Instance = ScriptableObject.CreateInstance
s_Instance.hideFlags = HideFlags.HideAndDontSave;
}
Init();
}
return s_Instance;
}
}
static void Init()
{
Instance.m_RTCache.Clear();
foreach (var v in Instance.m_Cache)
Instance.m_RTCache.Add(v.Key, v.Value);
}
internal static string GetValue(string key)
{
string v;
Instance.m_RTCache.TryGetValue(key, out v);
return v;
}
internal static void SetValue(string key,string value)
{
if (Instance.m_RTCache.ContainsKey(key))
{
Instance.m_RTCache[key] = value;
}
else
{
Instance.m_RTCache.Add(key, value);
Instance.m_Cache.Add(new SerializeProperty() { Key = key, Value = value });
}
}
internal static void Save()
{
InternalEditorUtility.SaveToSerializedFileAndForget(new Object[] { Instance }, s_AssetPath, true);
}
}
}
扩展ProjectSetting窗口需要用到SettingsProvider,详情参见官方文档,很详细
这里简单总结一下,SettingsProvider有两种用法,第一种是通过一个静态函数加标签创建SettingsProvider对象,然后通过里面的回调函数进行扩展
第二种是自己写一个类,继承SettingsProvider,然后通过override接口的方式进行扩展
这里我用的第一种方法,代码如下,供参考
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.UIElements;
namespace TBC.Editor
{
internal static class TBCProjectSettingsWindow
{
static GUIContent m_EditorSettingLabel = new GUIContent("Scriptable TBC Editor Settings");
static string m_EditorSettingAssetGUID = "_TBCFramework(EditorSettingAssetGUID)";
static Object m_EditorSettingAsset;
[SettingsProvider]
static SettingsProvider CreateTBCFrameworkSettingsProvider()
{
var provider = new SettingsProvider("Project/TBC Framework", SettingsScope.Project)
{
guiHandler = (searchContext) =>
{
EditorGUI.BeginChangeCheck();
EditorGUILayout.BeginVertical(GUI.skin.box);
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUILayout.LabelField(m_EditorSettingLabel);
var lastAsset = m_EditorSettingAsset;
m_EditorSettingAsset = EditorGUILayout.ObjectField(m_EditorSettingAsset, typeof(TBCEditorSetting), false);
if (m_EditorSettingAsset != lastAsset)
{
var path = m_EditorSettingAsset != null ? AssetDatabase.GetAssetPath(m_EditorSettingAsset) : null;
var guid = !string.IsNullOrEmpty(path) ? AssetDatabase.AssetPathToGUID(path) : null;
TBCProjectSettings.SetValue(m_EditorSettingAssetGUID, guid);
}
EditorGUILayout.EndVertical();
EditorGUILayout.EndVertical();
if (EditorGUI.EndChangeCheck())
TBCProjectSettings.Save();
},
activateHandler = (string a, VisualElement b) =>
{
var scriptableGuid = TBCProjectSettings.GetValue(m_EditorSettingAssetGUID);
if (!string.IsNullOrEmpty(scriptableGuid))
{
var path = AssetDatabase.GUIDToAssetPath(scriptableGuid);
m_EditorSettingAsset = !string.IsNullOrEmpty(path) ? AssetDatabase.LoadAssetAtPath
}
},
keywords = new HashSet
};
return provider;
}
}
}
如果要扩展Preferences只需要将枚举改成SettingsScope.User即可