The Fast Enter-to-Play mode is probably the most exciting feature in years and it will probably save months of waiting time during the project development cycle on our team.
It should’ve been the part of the Unity from the beginning but I’m still happy that Unity finally recognizes.
Unity routinely is asking for feedback but it really makes me sick whenever I hear them.
It’s not like we didn’t give Unity enough feedbacks but Unity does not listen and take actions from the user’s perspective.
It’s late nonetheless it’s a good start and I hope it continues.
The doc ( Entering PlayMode faster without domain and scene reloads - Google Docs ) is really good explaining how thing will change. However, it still lacks explaining how to work around it. If there is one asset causing a problem, this feature will not be usable, therefore I would like Unity to help the asset developers to adopt the new way of entering the play mode as fast/easily as possible. Having some use-cases where it can cause problems and how to work around it would be useful. And in order to do that, it will help to have a new API/Attributes, such as InitializeOnPlayToEnter(and perhaps ExitOnPlayToEnter) and etc.
This is the best thing ever happened in a long time and I can’t wait until 2019.3 releases. It can immediately save many hours, but adopting the new style will take a while, therefore we need to move as soon as we can.
I really hope this feature still be part of 2019.2 preview package. It will make the adoption 3-4 months earlier. This is still an optional preview that won’t break if not opt-in, right? Yeah, it will require some core changes but if users do not opt-in, just make the code path to take the old. I don’t think it’s that hard and I don’t see any harm doing it.
I’ll really appreciate in advance and it will make me think twice about Unity if you can push it. Look how many canceled project or delayed projects we had in the past? Can you please make it something to happen earlier just for once?
Thank you for taking time to read and the suggestions! I’ll add examples with issues to the doc.
We’ve been considering and are still considering adding an attribute. Having [InitializeOnEnteredPlayMode] which executes method static void MyPlaymodeSetup(EnterPlayModeOptions options) totally makes sense.
However, as mentioned above we already have https://docs.unity3d.com/ScriptReference/EditorApplication-playModeStateChanged.html event which can be used to clear the state. In some cases is has to be used in combination with other APIs which makes detection not simple (at all). Partially it is because PlayModeStateChange.EnteredPlayMode is fired too late after 2 updates when game code is technically already in playmode. I would rather fix this behavior first - we are looking if it is safe - and if not add an attribute.
I noticed according to the document the scene reset does not re-deserialise the objects in the scene. It just invokes awake and on enable. Consider the scenario where I have an object in my scene that has a behaviour that references another object. I hit play, and while the game is running I change the reference on that behaviour to a 3rd game object. When I hit stop, my behaviour isn’t “reset”? IE it’ll be referencing the 3rd object? Am I understanding this right?
If I understood correctly, when stopping it will still reset, as it backups the scene before playing, what does not occurs is a reload when entering play mode, so if you change a field of an object while in edit mode (for example, using the ExecuteInEditMode attribute) this field will not reset automatically when entering play mode.
When you say that you “backup current scenes” - what does that mean? If none of the current scenes are dirty, this should take zero time, since they can be loaded from file, right?
I submitted a bug: (Case 1168733) Fast Enter Playmode compatibility issue
The issue is that the default values can change in some circumstances.
This is happening in playmode only scripts so this is not an issue of something remaining from editor mode user code.
Here’s a test script:
using UnityEngine;
public class PlayModeTest : MonoBehaviour
{
private Vector3[] testVector;
private void Start()
{
if (testVector == null)
Debug.Log("Start: testVector is null");
else
Debug.Log("Start: testVector is not null");
}
}
If you trigger a recompile, THEN enter playmode it will report the variable as not null.
Subsequent playmode entries, or if you manually reload the scene than the variable will be null.
Found it in real production code - was quite unexpected even after reading the entire doc.
Not sure if the reply was to me, but if yes, I meant exactly that, as scenes with modifications needs to be backed up. If is doesn’t have modification it will not take “zero time” as it still requires to load from file, but it should be back to a “before play mode” state.
Thanks for the bug!
It is more likely scene reset fault when we soft reset alive scene objects. Could you please enable normal scene reload as a workaround.
InitializeOnLoadMethod is called only with the domain reload, so no, there is no need to unregister because there will be no second registration for the domain lifetime.
But yes, I like personally attributes way - less boilerplate code - I’ll add it.
When you exit playmode the scene is destroyed and reloaded from the backup, so you get unaltered scene state which was before you hit play. The exit playmode behavior stays exactly the same.
In that case you don’t want the editor code to be different from the play mode code. We’d need an attribute that fires either when we enter play mode, or when the build is launched.
In your example, and in @Peter77 's, having that code in builds would be harmless. For something like a must-be-initialized-at-startup-singleton, it’s necessary for the code to run in builds.
I think the #if boilerplate should be reserved for instances where you need different things to happen from builds to play mode.
I think the initialization code is often the same, whether you press play in the editor or if you actually start a player. At least in my code base. Thus I would prefer if we can use the same initialization method in both cases, to avoid having different initialization behaviour.
I think of something along the lines:
public class InitializeOnEnterPlayModeScript : MonoBehaviour
{
public static int GameStaticValue;
[RuntimeInitializeOnLoadMethod]
[UnityEngine.InitializeOnEnterPlayMode]
static void InitializeOnEnterPlayModeGameMethod()
{
GameStaticValue = 42;
}
}
Yes, agree. For this we have RuntimeInitializeOnLoadMethod attribute which is executed both in the Player and Editor during the scene load and doesn’t depend on domain reload happened or not.
And now that @Peter77 mentioned it in the example I understand that there is no need to use InitializeOnEnterPlayMode for game scripts and thus complement RuntimeInitializeOnLoadMethod with InitializeOnEnterPlayMode attribute as it is called anyway. (Although [RuntimeInitializeOnLoadMethod([RuntimeInitializeLoadType.BeforeSceneLoad](https://docs.unity3d.com/ScriptReference/RuntimeInitializeLoadType.BeforeSceneLoad.html))] should be used to make sure init happens before any Awake or OnEnable of game scripts).
I shouldn’t have used #if probably, sorry for confusion - that was a copy paste from a test script
The main reason for InitializeOnEnterPlayMode to exist is to provide a better entry point for resetting Editor scripts.
During Enter Play Mode there is a specific order in which magic callbacks are called for Editor scripts. And there is no way to reset singletons before the first Update happens due to EditorApplication.playModeStateChanged callback being called after the second Update - you basically need to use boilerplate in a form of Editor script with the lowest order index.
There is InitializeOnLoad attribute which does custom initialization for the Editor code, unfortunately we can’t use it in the path without domain reload as it breaks scripting state in 100% of cases we looked at. InitializeOnEnterPlayMode could be used to compliment InitializeOnLoad. However it is flexibility vs usability question (and somewhat performance)
Option 1:
public class MayEditorClass :
{
public static int StaticValue;
[InitializeOnLoadMethod]
static void MyInitializeOnLoadMethod()
{
StaticValue = 42;
}
[InitializeOnEnterPlayMode]
static void MyInitializeOnEnterPlayModeMethod(EnterPlayModeOptions options)
{
if (options.HasFlag(EnterPlayModeOptions.DisableDomainReload))
MyInitializeOnLoadMethod();
}
}
Option 2:
public class MayEditorClass :
{
public static int StaticValue;
[InitializeOnLoadMethod]
[InitializeOnEnterPlayMode]
static void MyInitializeMethod()
{
StaticValue = 42;
}
}
In the last example InitializeOnLoadMethod is called after domain reload, so if we choose it we have to make sure that a set of methods marked with InitializeOnLoadMethod is not called during processing of InitializeOnEnterPlayMode methods to be able to use InitializeOnEnterPlayMode universally for any Play Mode configuration.
I’m still waiting for 2019.3 to release asap to push other asset developers but I’m getting a bit worried.
Since my wish wasn’t granted (i.g., release this mode with 2019.2 as a preview so that we can test early on), I expect Unity will do thorough testing that all of Unity packages work out-of-box when it’s released in 2019.3, so that Unity itself is not the problem for the adoption.
I hope it’s not too much to ask and I would be very disappointed if Unity packages themselves are not working properly.
I got a reply from QA that [quote]
After investigation, our developers have decided that this behavior is expected.
[/quote]
Now let me be clear:
I know why the issue appears.
I know how to work around it, so I don’t need more help on that
I think the behavior is anything but expected.
It will cause a lot of headaches and random bugs for a lot of developers
Most people will not understand why it is happening and will see it as random failure.
So in this case I filed the bug to be helpful, not just for ourselves.
Just so you know, the generic workaround that WE found is:
If you have a private or internal field, that is a reference type (arrays, List<>, or a class marked [Serializable]), starting from 2019.3 you should mark them [NonSerialized]
Otherwise you might see seemingly random issues, that didn’t happen in previous Unity versions.