ScriptableSignleton.cs 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using UnityEditor;
  5. using UnityEditorInternal;
  6. using UnityEngine;
  7. namespace HybridCLR.Editor.Settings
  8. {
  9. public class ScriptableSingleton<T> : ScriptableObject where T : ScriptableObject
  10. {
  11. private static T s_Instance;
  12. public static T Instance
  13. {
  14. get
  15. {
  16. if (!s_Instance)
  17. {
  18. LoadOrCreate();
  19. }
  20. return s_Instance;
  21. }
  22. }
  23. public static T LoadOrCreate()
  24. {
  25. string filePath = GetFilePath();
  26. if (!string.IsNullOrEmpty(filePath))
  27. {
  28. var arr = InternalEditorUtility.LoadSerializedFileAndForget(filePath);
  29. s_Instance = arr.Length > 0 ? arr[0] as T : s_Instance??CreateInstance<T>();
  30. }
  31. else
  32. {
  33. Debug.LogError($"save location of {nameof(ScriptableSingleton<T>)} is invalid");
  34. }
  35. return s_Instance;
  36. }
  37. public static void Save(bool saveAsText = true)
  38. {
  39. if (!s_Instance)
  40. {
  41. Debug.LogError("Cannot save ScriptableSingleton: no instance!");
  42. return;
  43. }
  44. string filePath = GetFilePath();
  45. if (!string.IsNullOrEmpty(filePath))
  46. {
  47. string directoryName = Path.GetDirectoryName(filePath);
  48. if (!Directory.Exists(directoryName))
  49. {
  50. Directory.CreateDirectory(directoryName);
  51. }
  52. UnityEngine.Object[] obj = new T[1] { s_Instance };
  53. InternalEditorUtility.SaveToSerializedFileAndForget(obj, filePath, saveAsText);
  54. }
  55. }
  56. protected static string GetFilePath()
  57. {
  58. return typeof(T).GetCustomAttributes(inherit: true)
  59. .Where(v => v is FilePathAttribute)
  60. .Cast<FilePathAttribute>()
  61. .FirstOrDefault()
  62. ?.filepath;
  63. }
  64. }
  65. [AttributeUsage(AttributeTargets.Class)]
  66. public class FilePathAttribute : Attribute
  67. {
  68. internal string filepath;
  69. /// <summary>
  70. /// 单例存放路径
  71. /// </summary>
  72. /// <param name="path">相对 Project 路径</param>
  73. public FilePathAttribute(string path)
  74. {
  75. if (string.IsNullOrEmpty(path))
  76. {
  77. throw new ArgumentException("Invalid relative path (it is empty)");
  78. }
  79. if (path[0] == '/')
  80. {
  81. path = path.Substring(1);
  82. }
  83. filepath = path;
  84. }
  85. }
  86. }