- Home /
Detect Play mode about to be entered
I want to know when play mode is about to be entered.
For my case, EditorApplication.playmodeStateChanged and EditorApplication.isPlayingOrWillChangePlaymode does not work as they are called too late.
I need to check right after the scripts are recompiled so that I can prevent some reflection code in the editor from running and potentially slowing down the start of scene test. My tests revealed that the function is called while EditorApplication.isPlayingOrWillChangePlaymode is still false and the playmodeStateChanged is called even later than that.
Does anyone have a solution to this?
You said it's too late to use those two flags, so you want to get a notification immediately after you hit the play button?
Yes, because my EditorWindow might be open and then its OnEnable() will be called. I want to prevent a function from being called within the OnEnable since that function will be perfor$$anonymous$$g reflection which could potentially slow down the startup/ play (or I think it might).
It is not that big an issue but was hoping someone might know of a possibility in case I do run into a problem with this editor tool becomes more complicated.
Well my rule of thumb is not to solve a problem unless it's there, or you're sure you'll come across it. I do remember needing to detect entering into playmode, I think I hooked a static method into EditorApplication.update that checks if (!Application.isPlaying && EditorApplication.isPlayingOrWillChangePlaymode)
can't remember exactly but something like that. It triggered right after I hit play.
Thank you for this. EditorApplication.isPlayingOrWillChangePlaymode is exactly what I was looking for to solve this same problem. Thank you for providing the answer!
I'll investigate the EditorApplication.update option again. Seems like that and using EditorApplication.is... properties are the only things available.
Did some checking and my Reflect code is taking over 600ms so far. I've decided to not let it perform in the OnEnable() of the editor and only in OnFocus(). At least in this way when Play is pressed and the editor window is not visible then the reflection code will not run.
The reflection code will of course not run each time the window is focused since it checks if the reflect data is present. I guess anther solution would be to prevent clearing of the variable that holds the reflected data when play is pressed (but I do not know if this is possible).
Answer by aeroson · Jun 17, 2017 at 02:48 PM
After some debugging I found out you can detect this moment with:
EditorApplication.isPlaying = false && EditorApplication.timeSinceStartup == 0
It appears Unity internally works this way:
EditorApplication.isPlaying = false;
....
You Click Play in editor
....
EditorApplication.timeSinceStartup = 0;
Editor class OnDestroy on everything
-> here you can detect this moment by being in OnDestroy and EditorApplication.isPlaying = false && EditorApplication.timeSinceStartup == 0
...
Editor enters play mode
EditorApplication.isPlaying = true;
---
I needed to find this moment in releasable (non UnityEditor script), so I did this: ApplicationState static class. Iam using it to destroy dependant components and wanted to make it work both in editor and play mode:
public static void MyDestroy(Object obj)
{
if (ApplicationState.isAboutToEnterPlayMode)
// because at this moment we cant call neither Destroy nor DestroyImmediate
return;
if (ApplicationState.isPlaying)
Destroy(obj);
else
DestroyImmediate(obj);
}
Not working in 2021.1.16f1 the first Editor Update happens when Time.timeSinceLevelLoad == Time.deltaTime;
which is at the first Update()
call, after all Awake()
and Start()
Methods have been exectuted.
In my case, I am using ScriptableObject Variables, which have a "defaultValue" and a "runtimeValue" and I want to set the "runtimeValue" to "defaultValue" before entering play mode ... there seems to be no way to archive that behaviour. The solution I have right now just sets the value after Start and Awake calls, leading to all sorts of errors.
Answer by Ralidon · Aug 30, 2021 at 06:55 PM
Can InitializeOnLoadAttribute help you with this?
[InitializeOnLoadAttribute]
public static class PlayModeStateChangedExample
{
static PlayModeStateChangedExample()
{
EditorApplication.playModeStateChanged += ModeStateChanged ;
}
private static void ModeStateChanged (PlayModeStateChange state)
{
if (state == PlayModeStateChange.ExitingEditMode)
{
//do stuff
}
}
}
Answer by McFood · May 10 at 06:04 AM
Taken from another question about changing scenes when entering playmode.
RuntimeInitializeOnLoadMethodAttribute can mark methods to run during various Unity initialization steps.
RuntimeInitializeLoadType can be set to run before a scene is loaded, or after assemblies are loaded. Either of which might work for your use case depending on when your other code is running.
public static class DoSomething { [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType3.BeforeSceneLoad)] static void OnBeforeSceneLoad() { } [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)] static void OnAfterAssembliesLoaded() { } }