Reputation: 88
Is it possible to prevent Unity from changing the playmode after the user has pressed the button?
Let's say I have a custom editor which may have a state which can't be properly serialized; if user changes Unity Editor mode at this moment, their changes will be lost.
It is an option to completely get rid of non-serializeable state, but this is the task of completely different complexity. Would like to avoid that.
UPD:
I've tested derHugo's answer with the following script:
using UnityEditor;
using UnityEngine;
namespace Innoactive.Hub.Training.Editors
{
[InitializeOnLoad]
public class ProveThatDudeWrongWindow : EditorWindow
{
private static ProveThatDudeWrongWindow windowInstance;
private string notSerializedString = "default";
static ProveThatDudeWrongWindow()
{
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
}
[MenuItem("Test/I'm damn sure he's wrong")]
private static void MenuItem()
{
if (windowInstance == null)
{
windowInstance = GetWindow<ProveThatDudeWrongWindow>();
}
windowInstance.notSerializedString = "some value";
}
[MenuItem("Test/Display current value")]
private static void DisplayCurrentNonSerializedValue()
{
windowInstance = GetWindow<ProveThatDudeWrongWindow>();
Debug.Log("string: " + windowInstance.notSerializedString);
}
private static void OnPlayModeStateChanged(PlayModeStateChange state)
{
if (state == PlayModeStateChange.ExitingEditMode)
{
EditorApplication.isPlaying = false;
}
Debug.Log("state: " + state);
}
}
}
Then I've done the following:
Test/I'm damn sure he's wrong
option to set non-serialized value from default
value to some value
Test/Display current value
to make sure the value is changedTest/Display current value
to see current value. If it is default
, derHugo's solution does not work, if it is some value
, it works.Result: derHugo is cool.
Upvotes: 3
Views: 2939
Reputation: 90779
Yes there is I think
You can register to EditorApplication.playModeStateChanged
Look at the example from the doc I modified:
using UnityEngine;
using UnityEditor;
public static class PlayModeStateChangedExample
{
private static void LogPlayModeState(PlayModeStateChange state)
{
Debug.Log(state);
}
public static void SetPlayModeEnabled(bool enabled)
{
//This is possible since you allways can remove
//a listener even if there is none so far
//This allways removes the listener making sure it is only added once
EditorApplication.playModeStateChanged -= LogPlayModeState;
if(!enabled)
{
EditorApplication.playModeStateChanged += LogPlayModeState;
}
}
}
Now all that's left is resetting EditorApplication.isPlaying
back to false
e.g. by replacing
Debug.Log(state);
with
// This mode occures right before entering PlayMode
// and is the moment in which we want to intervene
if(state == PlayModeStateChange.ExitingEditMode)
{
EditorApplication.isPlaying = false;
}
to kill the PlayMode.
So you can call from anywhere e.g.
PlayModeStateChangedExample.SetPlayModeEnabled(false);
I'm not sure however if this would completely prevent the serialization part since it also states in the doc
Setting
isPlaying
delays the result until after all script code has completed for this frame.
Upvotes: 4