1

I have a ScriptableObject like this

enter image description here

and during Playmode I adjust the CurrenHealthValue

enter image description here

and when I exist the Playmode the CurrentHealthValue=80 doesn't return to 40, I know it was how ScriptableObject works but I want to know if there is any way which I can automatically return the 40 original value after exist the Playmode instead of manually rewrite the value to 40 before start the new Playmode.

Tien Hung
  • 139
  • 8
  • 1
    One way would be to instead of using the original SO create a runtime copy `Instantiate(yourSO)` .. won't work of course if multiple components access the same SO – derHugo Feb 20 '23 at 17:01
  • 1
    Here are some ideas https://answers.unity.com/questions/1664323/how-are-you-resetting-your-scriptable-objects-betw.html – derHugo Feb 20 '23 at 17:02

2 Answers2

5

In situations like this, I've used the EditorJsonUtility to save a copy of the initial object as JSON, and then overwritten the target object once I've finished.

In this case, the code would look something similar to:

using UnityEngine;
#if UNITY_EDITOR // makes intent clear.
using UnityEditor;
#endif

[CreateAssetMenu ( fileName = "TestScriptableObject", menuName = "TestScriptableObject", order = 1 )]
public class TestScriptableObject : ScriptableObject
{
    public int Field1;
    public float Field2;
    public Vector2 Field3;

#if UNITY_EDITOR
    [SerializeField] private bool _revert;
    private string _initialJson = string.Empty;
#endif

    private void OnEnable ( )
    {
#if UNITY_EDITOR
        EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
        EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
#endif
    }

#if UNITY_EDITOR
    private void OnPlayModeStateChanged ( PlayModeStateChange obj )
    {
        switch ( obj )
        {
            case PlayModeStateChange.EnteredPlayMode:
                _initialJson = EditorJsonUtility.ToJson ( this );
                break;

            case PlayModeStateChange.ExitingPlayMode:
                EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
                if ( _revert )
                    EditorJsonUtility.FromJsonOverwrite ( _initialJson, this );
                break;
        }
    }
#endif
}
Milan Egon Votrubec
  • 3,696
  • 2
  • 10
  • 24
2

You can actually subscribe your ScriptableObject class to Editor's play mode state changes. A small example which demonstrate that:

#if UNITY_EDITOR
    using UnityEditor;
#endif
using UnityEngine;

namespace SomeNameSpace
{
    [CreateAssetMenu(fileName = "TestScriptableObject", menuName = "ScriptableObjects/")]
    public class TestScriptableObject : ScriptableObject
    {
        private const int DefaultHealth = 120;
        
        public int Health = 60;

        private void OnEnable()
        {
#if UNITY_EDITOR
            // Subscribe for the "event"
            EditorApplication.playModeStateChanged += LogPlayModeState;
#endif
        }

        private void OnDisable()
        {
#if UNITY_EDITOR
            // Don't forget to unsubscribe
            EditorApplication.playModeStateChanged -= LogPlayModeState;
#endif
        }

#if UNITY_EDITOR
        private void LogPlayModeState(PlayModeStateChange state)
        {
            if (state == PlayModeStateChange.ExitingPlayMode)
            {
                // Reset / Set the default health value
                Health = DefaultHealth;
            }
        }
#endif
    }
}
hardartcore
  • 16,886
  • 12
  • 75
  • 101
  • 1
    A hardcoded default value isn't really helpful though .. OP wants to return to what was in the Inspector before – derHugo Feb 20 '23 at 16:59
  • 1
    It was just a suggestion. You can save the default value when the game has entered play mode and 'reset' the value in exiting playing mode. – hardartcore Feb 21 '23 at 09:36