Configurable Enter Play Mode Compatibility
The documentation has moved to: https://mitschmr-studios.io/documentation/api-guides/configurableenterplaymodecompatibility.html
This version will no longer be updated and maintained.
With 2019.3, Unity released a brand new feature called the Configurable Enter Play Mode, which can drastically reduce the time it takes to enter the play mode inside the Unity Editor. Read more about it on the page linked above or the blog post.
Problems
The two options, namely Reload Domain and Reload Scene, either disable the resetting of the script state or the scene reload when enter play mode. Naturally, this brings some problems with itself.
Domain Reloading
When disabling this feature, static fields do not get reset and static event handlers will not unregister methods, meaning that when entering the play mode the methods get registered again. This may be very undesired and can cause troubles.
For more information, see here.
Scene Reloading
Disabling this feature makes Unity no longer destroying all existing scene gameobjects and reloading everything from disk, but only recreates the modified content of the scene. This has the consequence that certain ScriptableObject and MonoBehaviour fields keep their values and that scripts that use the ExecuteInEditMode
or ExecuteAlways
attribute do not receive OnDestroy
or Awake
calls.
For more information, see here.
Game Creator
Game Creator itself uses not only static fields but also the ExecuteInEditMode
attribute, meaning that there are errors thrown when enabling either of these options. We will tackle this in this guide, read how to below.
What To Do
Requirements
This tutorial uses Unity 2019.4.24f1 and the latest versions of GC and the modules at this point (GC v1.1.12, Inventory v1.1.3, Quests v1.0.2, Stats v1.1.3, 04/20/2021).
Analyzing
First we need to analyze which classes in Game Creator and the modules use either of the mentioned things above. These are the following:
Game Creator standalone:
AudioManager
Character
CharacterHeadTrack
CoroutinesManager
EventDispatchManager
EventSystemManager
GlobalID
GlobalVariablesManager
LocalizationManager
PlayerCharacter
PoolManager
RememberActive
SaveLoadManager
SimpleMessageManager
Singleton<T>
TimeManager
TouchStickManager
Inventory:
InventoryManager
MerchantManager
Quests:
QuestsManager
Stats:
Stats
3rd party modules:
The safest way to know which classes are affected is by asking the module owner. Still, you can also find it out by yourself. Open the GlobalID
script with your scripting environment (like Visual Studio) and check the references of the class. It is very unlikely for a module to use the ExecuteInEditMode
attribute. Once found out, follow the instructions below.
Managers first
The first thing we want to do is change the base class of every manager class, because there are 14 deriving from Singleton<T>
. We add the following code after the "Constructor" comment and before the [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
attribute:
What does this code do? When the Reload Domain feature is unchecked, the attribute RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
is called, the method Init
gets executed which resets the static variable instance
and sets the IS_Exiting
bool variable to false. Normally, the second one is not necessary, but with Reload Scene disabled, the method OnRuntimeStartSingleton
is not executed and thus we need to set it.
The next point on the list is to add the following code to each of the manager classes:
Replace <className> with the name of the class of the manager. Here are a few examples:
What does this code do? As we have seen before, when Reload Domain is disabled, the attribute in the code is called. The <className>.Init();
tells the manager to be initialized (reset) when the play mode is entered.
Components second
Game Creator and the modules feature a variety of components to add to the gameobjects. But the base class, GlobalID
, also uses the ExecuteInEditMode
attribute. This means we can't use the Awake
method. We need to change it like this for all classes that derive from GlobalID
:
Add a private boolean variable called
initialized<className>
, i.e.initializedStats
, with the value falseIf there is an
Awake
method, rename it toOnEnable
If you are not in the
GlobalID
class, add theOverride
keyword after the modifier if it is not already thereMove the code in the renamed method behind an if condition that checks for the negative value of the newly created boolean variable
If there already is an
OnEnable
method, merge the two of them together, whereas the code of the oldOnEnable
method after the closing of the if condition comes
Let's take a look at an example:
Another example with existing OnEnable
method:
Known Issues & Workarounds
Problem: You may experience the triggers On Mouse Left Click, On Mouse Middle Click and On Mouse Right Click (maybe some other triggers as well) to not be working when Reload Scene is deactivated.
Answer: Make sure to add the components Physics Raycaster
and Physics 2D Raycaster
to the main camera. When Reload Scene is deactived, Unity doesn't check the gameobjects whether they have dependencies to the named components and thus won't add them.
Last updated