Search Unity

Insanely Fast Enter-to-Play mode

Discussion in '2019.3 Alpha' started by chrisk, Jun 27, 2019.

  1. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    469
    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 ( https://docs.google.com/document/d/...j-Pd9M71Uz9dc-dg4/edit#heading=h.2gazcsgmxkub ) 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?

    Cheers!
     
    Last edited: Jun 28, 2019
  2. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    4,161
    alexeyzakharov likes this.
  3. alexeyzakharov

    alexeyzakharov

    Unity Technologies

    Joined:
    Jul 2, 2014
    Posts:
    263
    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.
     
    Alverik, Yozaro, Peter77 and 2 others like this.
  4. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    3,903
    In this case, the boiler-plate code would be more right?

    Rather than being able to just do:
    Code (CSharp):
    1. class Cat : MonoBehaviour
    2. {
    3.     static int s_TotalMeows;
    4.    
    5.     [InitializeOnEnteredPlayMode]
    6.     static void OnEnteredPlayMode()
    7.     {
    8.         s_TotalMeows = 0;
    9.     }
    10. }
    We would need to have something like:
    Code (CSharp):
    1. class Cat : MonoBehaviour
    2. {
    3.     static int s_TotalMeows;
    4.  
    5. #if UNITY_EDITOR
    6.     static void OnEnteredPlayMode(UnityEditor.PlayModeStateChange value)
    7.     {
    8.         if (value == UnityEditor.PlayModeStateChange.ExitingEditMode)
    9.         {
    10.             s_TotalMeows = 0;
    11.         }
    12.     }
    13.  
    14.     [UnityEditor.InitializeOnLoadMethod]
    15.     static void RegisterCallback()
    16.     {
    17.         UnityEditor.EditorApplication.playModeStateChanged += OnEnteredPlayMode;
    18.     }
    19. #endif
    20. }
    Would I also need to unregister the playModeStateChanged callback with this new feature?
     
  5. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    735
    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?
     
  6. brunocoimbra

    brunocoimbra

    Joined:
    Sep 2, 2015
    Posts:
    21
    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.
     
    alexeyzakharov likes this.
  7. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,116
    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?
     
    alexeyzakharov likes this.
  8. Hyp-X

    Hyp-X

    Joined:
    Jun 24, 2015
    Posts:
    151
    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:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class PlayModeTest : MonoBehaviour
    4. {
    5.     private Vector3[] testVector;
    6.  
    7.     private void Start()
    8.     {
    9.         if (testVector == null)
    10.             Debug.Log("Start: testVector is null");
    11.         else
    12.             Debug.Log("Start: testVector is not null");
    13.     }
    14. }
    15.  
    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.
     
  9. brunocoimbra

    brunocoimbra

    Joined:
    Sep 2, 2015
    Posts:
    21
    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.
     
  10. alexeyzakharov

    alexeyzakharov

    Unity Technologies

    Joined:
    Jul 2, 2014
    Posts:
    263
    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.
     
  11. alexeyzakharov

    alexeyzakharov

    Unity Technologies

    Joined:
    Jul 2, 2014
    Posts:
    263
    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.
     
    brunocoimbra and Peter77 like this.
  12. alexeyzakharov

    alexeyzakharov

    Unity Technologies

    Joined:
    Jul 2, 2014
    Posts:
    263
    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.
     
    brunocoimbra likes this.
  13. alexeyzakharov

    alexeyzakharov

    Unity Technologies

    Joined:
    Jul 2, 2014
    Posts:
    263
    Yes, you are right. If scene is not dirty backup is pointing to the original scene file.
    (I'll add it to the doc, thanks for pointing this out)
     
  14. alexeyzakharov

    alexeyzakharov

    Unity Technologies

    Joined:
    Jul 2, 2014
    Posts:
    263
    Would you use such boilerplate to catch EnterPlaymode and do reset or other Editor work for game code?
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. #if UNITY_EDITOR
    4. using UnityEditor;
    5. #endif // UNITY_EDITOR
    6. public class InitializeOnEnterPlayModeScript : MonoBehaviour
    7. {
    8.     public static int GameStaticValue = 42;
    9. #if UNITY_EDITOR
    10.     [InitializeOnEnterPlayMode]
    11.     static void InitializeOnEnterPlayModeGameMethod(EnterPlayModeOptions options)
    12.     {
    13.         if (!options.HasFlag(EnterPlayModeOptions.DisableDomainReload))
    14.             return;
    15.         GameStaticValue = 42;
    16.     }
    17. #endif // UNITY_EDITOR
    18. }
     
  15. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,116
    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.
     
    Griz, Peter77 and Lars-Steenhoff like this.
  16. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    3,903
    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:
    Code (CSharp):
    1. public class InitializeOnEnterPlayModeScript : MonoBehaviour
    2. {
    3.     public static int GameStaticValue;
    4.  
    5.     [RuntimeInitializeOnLoadMethod]
    6.     [UnityEngine.InitializeOnEnterPlayMode]
    7.     static void InitializeOnEnterPlayModeGameMethod()
    8.     {
    9.         GameStaticValue = 42;
    10.     }
    11. }
     
    alexeyzakharov likes this.
  17. alexeyzakharov

    alexeyzakharov

    Unity Technologies

    Joined:
    Jul 2, 2014
    Posts:
    263
    Thanks for the replies!
    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([URL='https://docs.unity3d.com/ScriptReference/RuntimeInitializeLoadType.BeforeSceneLoad.html']RuntimeInitializeLoadType.BeforeSceneLoad[/URL])]
    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:
    Code (CSharp):
    1. public class MayEditorClass :
    2. {
    3.     public static int StaticValue;
    4.     [InitializeOnLoadMethod]
    5.     static void MyInitializeOnLoadMethod()
    6.     {
    7.         StaticValue = 42;
    8.     }
    9.     [InitializeOnEnterPlayMode]
    10.     static void MyInitializeOnEnterPlayModeMethod(EnterPlayModeOptions options)
    11.     {
    12.         if (options.HasFlag(EnterPlayModeOptions.DisableDomainReload))
    13.             MyInitializeOnLoadMethod();
    14.     }
    15. }
    Option 2:
    Code (CSharp):
    1. public class MayEditorClass :
    2. {
    3.     public static int StaticValue;
    4.  
    5.     [InitializeOnLoadMethod]
    6.     [InitializeOnEnterPlayMode]
    7.     static void MyInitializeMethod()
    8.     {
    9.         StaticValue = 42;
    10.     }
    11. }
    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.
     
  18. AlkisFortuneFish

    AlkisFortuneFish

    Joined:
    Apr 26, 2013
    Posts:
    576
    Been trying this out and found Addressables throwing a bit of a wobbly with it. Submitted a bug report with a repro, as well as a thread here.
     
  19. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    469
    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.