From e7f5d778e105fcd6e58853ca5fc47cb46e1f35cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=80=9D=E6=B5=B7?= <10001@qq.com> Date: Fri, 14 Feb 2025 18:45:27 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Editor/Misc/ScriptableSingleton.cs | 98 ++++++++++++++++++++ Editor/Misc/ScriptableSingleton.cs.meta | 3 + Runtime/Base/Exception/GameFrameworkGuard.cs | 2 +- 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 Editor/Misc/ScriptableSingleton.cs create mode 100644 Editor/Misc/ScriptableSingleton.cs.meta diff --git a/Editor/Misc/ScriptableSingleton.cs b/Editor/Misc/ScriptableSingleton.cs new file mode 100644 index 0000000..0bf222c --- /dev/null +++ b/Editor/Misc/ScriptableSingleton.cs @@ -0,0 +1,98 @@ +using System; +using System.IO; +using System.Linq; +using UnityEditorInternal; +using UnityEngine; + +namespace AlicizaX.Editor.Setting +{ + public class ScriptableSingleton : ScriptableObject where T : ScriptableObject + { + private static T s_Instance; + + public static T Instance + { + get + { + if (!s_Instance) + { + LoadOrCreate(); + } + + return s_Instance; + } + } + + public static T LoadOrCreate() + { + string filePath = GetFilePath(); + if (!string.IsNullOrEmpty(filePath)) + { + var arr = InternalEditorUtility.LoadSerializedFileAndForget(filePath); + s_Instance = arr.Length > 0 ? arr[0] as T : s_Instance ?? CreateInstance(); + } + else + { + Debug.LogError($"save location of {nameof(ScriptableSingleton)} is invalid"); + } + + return s_Instance; + } + + public static void Save(bool saveAsText = true) + { + if (!s_Instance) + { + Debug.LogError("Cannot save ScriptableSingleton: no instance!"); + return; + } + + string filePath = GetFilePath(); + if (!string.IsNullOrEmpty(filePath)) + { + string directoryName = Path.GetDirectoryName(filePath); + if (!Directory.Exists(directoryName)) + { + Directory.CreateDirectory(directoryName); + } + + UnityEngine.Object[] obj = new T[1] { s_Instance }; + InternalEditorUtility.SaveToSerializedFileAndForget(obj, filePath, saveAsText); + } + } + + protected static string GetFilePath() + { + return typeof(T).GetCustomAttributes(inherit: true) + .Where(v => v is FilePathAttribute) + .Cast() + .FirstOrDefault() + ?.filepath; + } + } + + [AttributeUsage(AttributeTargets.Class)] + public class FilePathAttribute : Attribute + { + internal string filepath; + + /// + /// 单例存放路径 + /// + /// 相对 Project 路径 + public FilePathAttribute(string path) + { + if (string.IsNullOrEmpty(path)) + { + throw new ArgumentException("Invalid relative path (it is empty)"); + } + + if (path[0] == '/') + { + path = path.Substring(1); + } + + filepath = path; + } + } +} diff --git a/Editor/Misc/ScriptableSingleton.cs.meta b/Editor/Misc/ScriptableSingleton.cs.meta new file mode 100644 index 0000000..6a3bddc --- /dev/null +++ b/Editor/Misc/ScriptableSingleton.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9da8cbe84b4045d093d326334bbf4c7f +timeCreated: 1739529382 \ No newline at end of file diff --git a/Runtime/Base/Exception/GameFrameworkGuard.cs b/Runtime/Base/Exception/GameFrameworkGuard.cs index 6300323..6a5d1d3 100644 --- a/Runtime/Base/Exception/GameFrameworkGuard.cs +++ b/Runtime/Base/Exception/GameFrameworkGuard.cs @@ -28,7 +28,7 @@ namespace AlicizaX.Runtime /// 要检查的值。 /// 值的名称。 /// 当值为null时引发。 - public static void NotNull(T value, string name) where T : class + public static void NotNull(T value, string name) where T : class { if (value == null) {