Hot Reloads & Live Recompilation - antfarmar/Unity-3D-Asteroids GitHub Wiki

Problem:

Hot-Reloading/Live-Compilation is unforgiving.

When debugging and/or editing code while in playmode, if you save the changes and return to the Unity editor, Unity will hot-reload/live-compile the code. This can be a quite handy time-saver during development, so it is definitely worth investigating this process to be sure your code is compatible with it to preserve it. It is quite touchy, though:

The process goes something like this:

  • Unity notices that the code has changed and tries to recompile it.
    • It first calls OnDisable, recompiles, the calls OnEnable when finished.
  • If the recompilation is successful, Unity does the hot-reload which:
    • Serializes everything it can.
    • Tears down the managed (Mono) runtime.
    • Starts a new managed (Mono) runtime with the new code.
    • De-serializes everything it can back into the new runtime.

There are many reasons why this might go wrong:

  • Anything which can’t be serialized...won’t be. That data will be lost, leading to null-references.
  • Static class members aren’t serialized, leading to null-references.
  • Name changes to serialized fields won’t make it through to the new runtime either, leading to null-references.
Further Reading:

Blog Post

Solution

Use only serializable types & exploit OnEnable/OnDisable messages.
  • Use ONLY serializable types!
    • It's not that difficult to emulate Dictionaries/Queues with Lists.
    • Limit your static types & singletons.
    • Data can be saved OnDisable, reassigned OnEnable
  • If static types/singleton instances are unavoidable:
    • They can be reassigned OnEnable.
    • It worked with the GameManager public instance (in the hot-reload branch).
  • Be cognizant of what you place in OnDisable/OnEnable.
    • These Event Messages are called on recompilation start/end, respectively.
    • Re-assign/initialize static variables here.
    • Don't put place code in here that naturally belongs in Awake/Start.
      • e.g. Once-only initializations & operations
  • Add [FormerlySerializedAs("oldFieldName")] to fields before renaming field.

Considerations

It is better to take advantage of things like dictionaries, queues, static classes, object references, etc, rather than the minor advantages that hot-reloading provides (which is probably not sustainable as a project grows anyhow). One should prefer clean, efficient, readable code and architecture over most things that would sacrifice it.