Search Unity

EditorWindow: How to tell when returned to editor mode from play mode??

Discussion in 'Immediate Mode GUI (IMGUI)' started by StunAustralia, Jul 21, 2018.

  1. StunAustralia

    StunAustralia

    Joined:
    Jul 1, 2018
    Posts:
    33
    Hi folks

    So I have a little EditorWindow... when I enter play mode OnDisable() is called, and then OnEnable(). This is 100% OK with me and matches what the docs seem to say.

    However, when I stop play mode and re-enter the editor, OnDisable() and OnEnable() are not called again. I expected it to be - the docs would seem to suggest so.

    So:
    1. is the behaviour I'm experiencing what it should be?
    2. and, if so, how best to detect the return to editor mode?
    (Just in case I've typo'd/confused myself/hit a weird edge case ... here's the very simple window I'm verifying this with)
    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3.  
    4. public class MyEditorWindow : EditorWindow
    5. {
    6.    [MenuItem("Window/MyEditorWindow")]
    7.    public static void ShowWindow() {
    8.       EditorWindow.GetWindow(typeof(MyEditorWindow)).Show();
    9.    }
    10.  
    11.  
    12.    void OnEnable() {
    13.       Debug.Log("OnEnable()");
    14.    }
    15.      
    16.  
    17.    void OnDisable() {
    18.       Debug.Log("OnDisable()");
    19.    }
    20.  
    21. }
    22.  
     
  2. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,618
  3. StunAustralia

    StunAustralia

    Joined:
    Jul 1, 2018
    Posts:
    33
    I had seen that on my wanderings, but without OnEnable() and OnDisable() firing as expected (although they do, at least, fire in pairs) I worried that I'd end up with subscribe/unsubscribe issues. Would you think subscription/unsubscription Awake() and OnDestroy() would be sufficient?

    (nice work on the Vector3 experiments by the way)
     
  4. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,317
    Simple fix:

    Code (CSharp):
    1. EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
    2. EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
     
  5. StunAustralia

    StunAustralia

    Joined:
    Jul 1, 2018
    Posts:
    33
    I'm going to try that in the Awake() and the -= in OnDestroy() - hopefully that'll bookend well enough :)

    Thanks all!

    I'm assuming since no one said any different, that the OnEnable() and OnDisable() pair do indeed fire when entering play mode but not exiting it. That seems strange to me, but if that's the way it works, that's the way it works!
     
  6. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,317
    This is correct. The OnDisable/OnEnable pair will get called whenever the assembly is reloaded. When entering play mode, the assembly is reloaded. The assembly is not reloaded when exiting play mode, thus these methods don't get called.
     
  7. StunAustralia

    StunAustralia

    Joined:
    Jul 1, 2018
    Posts:
    33
    That, I think, may well be the insight I've been lacking as I assumed it was unloaded and reloaded on both occasions!
     
  8. StunAustralia

    StunAustralia

    Joined:
    Jul 1, 2018
    Posts:
    33
    Ok... that didn't work as expected :( Here's the window I used:

    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3.  
    4. public class MyEditorWindow : EditorWindow {
    5.    [MenuItem("Window/MyEditorWindow")]
    6.    public static void ShowWindow() {
    7.       EditorWindow.GetWindow(typeof(MyEditorWindow)).Show();
    8.    }
    9.    private void Awake()    {
    10.       Debug.Log("Awake()");
    11.       EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
    12.       EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
    13.    }
    14.    
    15.  
    16.    private void OnDestroy()    {
    17.       Debug.Log("OnDestroy()");
    18.       EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
    19.    }
    20.  
    21.    private void OnPlayModeStateChanged(PlayModeStateChange state)    {
    22.          Debug.Log(state.ToString());
    23.    }
    24. }
    And here's what got logged to the console:

    Awake()          // occurred when I opened the window

    ExitingEditMode  // occurred when I pressed play

                     // nothing occurred when I pressed stop to exit play mode

    OnDestroy()      // When I closed the window



    Did I miss something obvious?
     
  9. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,697
    I use OnEnable() and OnDisable():

    TestWindow.cs
    Code (csharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3.  
    4. public class TestWindow : EditorWindow
    5. {
    6.  
    7.     [MenuItem("Tools/Test Window")]
    8.     public static void OpenTestWindow()
    9.     {
    10.         GetWindow<TestWindow>("Test");
    11.     }
    12.     private void OnEnable()
    13.     {
    14.         Debug.Log("OnEnable: registering playModeStateChanged");
    15.         EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
    16.         EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
    17.     }
    18.  
    19.     private void OnDisable()
    20.     {
    21.         Debug.Log("OnDisable: unregistering playModeStateChanged");
    22.         EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
    23.     }
    24.  
    25.     private void OnPlayModeStateChanged(PlayModeStateChange state)
    26.     {
    27.         Debug.Log("PlayModeStateChanged: " + state);
    28.     }
    29. }
    The "-=" preceding "+=", as madgvox mentioned, ensures that it's only registered once.

    The order of events:

    Open window:
    OnEnable: registering playModeStateChanged

    Start play mode:
    PlayModeStateChanged: ExitingEditMode
    OnDisable: unregistering playModeStateChanged
    OnEnable: registering playModeStateChanged
    PlayModeStateChanged: EnteredPlayMode

    Stop play mode:
    PlayModeStateChanged: ExitingPlayMode
    PlayModeStateChanged: EnteredEditMode

    Close window:
    OnDisable: unregistering playModeStateChanged
     
    invisage, Dustin_00 and cecarlsen like this.
  10. StunAustralia

    StunAustralia

    Joined:
    Jul 1, 2018
    Posts:
    33
    Thanks so much for that... I've saved that in my references!

    I guess it's my OCD or maybe just familiarity with other systems that I'm used to things being a little more symmetrical for initialise/cleanup. Having a state change that calls disable without a corresponding return to state without a corresponding enable is like fingernails down the blackboard of my soul!

    Having said that, I know all of Unity's GUI is written using the same system as are your PixelCrushers interfaces which I've just checked out.... so clearly it's a powerful system and I need to adjust my approach... just waiting for that 'click' to go off in my brain :)

    Thanks for all of your help and time folks... I really appreciate it!
     
    arielfel and TonyLi like this.