コンポーネントパターンを適用した ScriptableObject のベースクラスです。
ソースコード
public class ComponentScriptableObject : ScriptableObject { [SerializeField] protected List<ScriptableObject> m_Components = new(); protected ScriptableObject Add(Type type) { if (type.IsClass && !type.IsAbstract && type.IsSubclassOf(typeof(ScriptableObject))) { var component = CreateInstance(type) as ScriptableObject; AssetDatabase.AddObjectToAsset(component, this); m_Components.Add(component); if (component is ComponentScriptableObject componentScriptableObject) { componentScriptableObject.AddRequirements(); } return component; } throw new ArgumentException(type.GetTypeInfo().Name); } protected virtual IEnumerable<Type> Requirements() { yield break; } private void AddRequirements() { Requirements().ToList().ForEach(type => Add(type)); } protected List<T> GetAllInChildren<T>() where T : ScriptableObject { var list = m_Components.Where(x => x is T).Cast<T>().ToList(); list.AddRange(list.Where(x => x is ComponentScriptableObject).Cast<ComponentScriptableObject>().SelectMany(x => x.GetAllInChildren<T>()).ToList()); return list; } protected static T Create<T>(string path) where T : ScriptableObject { var data = CreateInstance<T>(); AssetDatabase.CreateAsset(data, path); if (data is ComponentScriptableObject componentScriptableObject) { componentScriptableObject.AddRequirements(); } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); return data; } protected static T Load<T>(string path) where T : ScriptableObject { var data = AssetDatabase.LoadAssetAtPath<T>(path); if (data == null) { return null; } if (data is ComponentScriptableObject componentScriptableObject) { var settings = componentScriptableObject.m_Components.Select(x => x.GetType()).ToList(); componentScriptableObject.Requirements().Where(type => !settings.Contains(type)).ToList().ForEach(type => componentScriptableObject.Add(type)); } return data; } } public abstract class ComponentScriptableObject<T1> : ComponentScriptableObject where T1 : ScriptableObject { public T Add<T>() where T : T1 { return Add(typeof(T)) as T; } public void RemoveAll<T>() where T : T1 { var components = GetAllInChildren<T>(); foreach (var component in components) { m_Components.Remove(component); DestroyImmediate(component, true); } m_Components.RemoveAll(x => x is T); } public bool TryGet<T>(out T component) where T : T1 { component = Get<T>(); return component != null; } public T Get<T>() where T : T1 { return m_Components.FirstOrDefault(x => x is T) as T; } public List<T> GetAllInChildren<T>() where T : T1 { return base.GetAllInChildren<T>(); } public static T Create<T>(string path) where T : T1 { return ComponentScriptableObject.Create<T>(path); } public static T Load<T>(string path) where T : T1 { return ComponentScriptableObject.Load<T>(path); } }