Search Unity

Resolved Simple way how to reset SO to default values when play mode finish

Discussion in 'Scripting' started by MartinMa_, May 6, 2023.

  1. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    Hello guys please how can I do it?
    I want every time I leave play mode all values are reseted to default, I attached screen.

    Is the only way to subscribe to editor even when play mode finish?


    I want that when playmode finish value is set back to 0.I found out that if i set it as not serialized filed value is changed to default but i want serialize it because sometimes this default value is 0 and sometimes it can be different based what i set in editor

    Thanks
     

    Attached Files:

  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,859
    You can easily make an editor tool that checks for certain types, an attribute, or an interface, and finds them all to reset them on play mode exit.

    I did so with an interface, so here's a cut down implementation:

    The simple interface:
    Code (CSharp):
    1. public interface IResetOnPlaymodeExit : IResetable
    2. {
    3. #if UNITY_EDITOR
    4.     public void PlaymodeExitReset();
    5. #endif
    6. }
    And a simple static class:
    Code (CSharp):
    1. #if UNITY_EDITOR
    2. [InitializeOnLoad]
    3. public static class AssetResetManager
    4. {
    5.     static AssetResetManager()
    6.     {
    7.         EditorApplication.playModeStateChanged += HandleAssetReset;
    8.     }
    9.    
    10.     private static void HandleAssetReset(PlayModeStateChange playModeStateChange)
    11.     {
    12.         if (playModeStateChange == PlayModeStateChange.ExitingPlayMode)
    13.         {
    14.             ResetAllIResetOnPlayModeExitAssets();          
    15.         }
    16.     }
    17.    
    18.     private static void ResetAllIResetOnPlayModeExitAssets()
    19.     {
    20.         List<Object> resetAssets = ObjectUtilities.FindAssets<Object>(x => x is IResetOnPlaymodeExit);
    21.  
    22.         if (resetAssets.Count == 0)
    23.         {
    24.             return;
    25.         }
    26.  
    27.         foreach (var asset in resetAssets)
    28.         {
    29.             ((IResetOnPlaymodeExit)asset).PlaymodeExitReset();
    30.         }
    31.  
    32.         Debug.Log($"Asset Reset Manager: Reset {resetAssets.Count} assets after exiting play mode.");
    33.     }
    34. }
    35. #endif
    You can easily expand upon the concept.

    Nonetheless, I would also suggest not storing runtime changing values in scriptable objects unless needed. Sometimes are better left in monobehaviours.
     
  3. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,433
    Honestly, I hate how Scriptable Objects has a completely different change paradigm to Scene objects, yet share the same Inspector UI. It's the worst part of SO, by far. I constantly have to check myself when making a little what-if change during gameplay, to decide if I'm going to mess up an SO (including one of the many SOs of Unity like lighting assets) or not.
     
    TheNullReference likes this.
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,859
    Except scriptable objects are project assets. Any project asset behaves like this if you change their values at runtime. It's not unique to SO's, it's just a side effect of what they are.

    There's no reason why scriptable objects should behave any different to other assets.
     
  5. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,433
    I think conversely, there's no reason why project assets should behave differently from any other scene object in the Inspector without an obvious indication of that difference. Mind you, special Inspector upgrades like Odin or InspectorGadgets compound the likelihood by letting you just fold out the content of almost anything serializable from the scene components that refer to them, but there are cases in custom drawers in stock Unity too.
     
  6. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,859
    If project assets were to reset on play mode exit, that would've have to been the desired and intended behaviour from day one, I think. It's a bit late to want that change, I think.

    We know why scenes 'reset'. When you enter play mode your scene gets backed up, and a whole new scene is loaded in, making everything taking place effectively transient. When you exit playmode, you're returned to the backed up scene(s). To do the same for project assets sounds... like it wouldn't be very performant.

    Mind you people often ask for their playmode changes to persist when exiting play mode, so there's that. The option either way would be welcome. Maybe attributes like
    [ResetOnPlayModeExit]
    for scriptable objects and
    [PersistOnPlayModeExit]
    for monobehaviours.

    In the former case it's pretty easy to roll your own solution, like I have.

    In any case I try to treat project assets as read only 99.99% of the time. If I want some 'runtime' values, I'll wrap said asset in a plain class that manages that. Or I use my reset utility.
     
  7. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    Thank you guys for your posts. I found out that issue in my case was that i was directly changing values on my SO and it was wrong. I needed to rework my logic so i use SO only as data container now if i want change these values i need to create new instance of everything. Like this. ConstructableDefinition is my ScriptableObject reference
    Code (CSharp):
    1. currentResources = new List<Resource>();
    2.         foreach (var VARIABLE in constructableDefinition.getReciepe().resourceList)
    3.         {
    4.             currentResources.Add(new Resource(VARIABLE.resourceType, 0));
    5.         }