// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // Unity using UnityEditor; using UnityEngine; namespace AWS.GameKit.Editor.Utils { /// <summary> /// A ScriptableObject which survives when the Unity editor restarts or does a Domain Reload. /// /// The object automatically writes itself to disk during OnDisable() and can be loaded with LoadObject(). /// </summary> public class PersistentScriptableObject<T> : ScriptableObject where T : PersistentScriptableObject<T> { private string _assetFilePath; private bool _shouldBeSaved; /// <summary> /// Load the ScriptableObject from a file on disk. /// </summary> /// <param name="assetFilePath">The path where the ScriptableObject's file will be loaded from and written to.</param> /// <returns>The ScriptableObject deserialized from the file.</returns> public static T LoadFromDisk(string assetFilePath) { T scriptableObject = AssetDatabase.LoadAssetAtPath<T>(assetFilePath); if (scriptableObject == null) { scriptableObject = CreateInstance<T>(); AssetDatabase.CreateAsset(scriptableObject, assetFilePath); } if (!string.IsNullOrEmpty(assetFilePath)) { scriptableObject._assetFilePath = assetFilePath; scriptableObject._shouldBeSaved = true; } return scriptableObject; } private void WriteToDisk() { // Implementation note: // We persist a clone instead of the original object to ensure the state is non-null when loaded by LoadAssetAtPath() in LoadFromDisk(). // If we persist the object by other means, then LoadAssetAtPath() returns null when LoadFromDisk() is called immediately after script recompilation. _shouldBeSaved = false; T clonedScriptableObject = (T)Instantiate(this); AssetDatabase.CreateAsset(clonedScriptableObject, _assetFilePath); } private void OnDisable() { if (_shouldBeSaved) { WriteToDisk(); } } } }