Features

Supported Features

  • Editing functions in monobehaviours, normal classes or static classes

    • You can edit the body of the function in any way that is valid C#. We recompile the whole function, so it works the same as you’re already used to.
  • Editing lambda methods

    • If you modify a lambda, we hot-reload the existing lambda. So for example, store a lambda in a static field during startup, and then edit the lambda without running startup code, your change to the lambda will still apply immediately.
  • Editing lambda methods with closures

    • If you use an outside variable inside your lambda, your lambda will work as usual. If you use a new outside variable, then your lambda will be hot-reloaded only when you create it again. for example the lambda in Array.Sort(() => …) is recreated every time you run the code, so it will always work as expected.
  • Editing async/await methods

  • Editing properties (get/set)

  • Editing events (add/remove)

  • Editing indexers (square bracket access such as dictionaries)

  • Editing operators methods (explicit and implicit operators)

  • Editing conversion operators methods such as == and +=

  • Adding/Editing/Removing constructors of classes

  • Adding/Editing/Removing local functions

  • Changing a method from async to sync, or from sync to async

  • Deleting any methods, properties, fields, class

  • Adding/editing/removing using directives. E.g. Using UnityEngine

  • Adding/Editing variable initializers. E.g. private int x = 1 in a class

    • E.g. int myField = 10. Do note that variables are only initialized when you create a new class instance. We don’t re-run variable initializers for already instantiated classes, as it could break existing code.
  • Use of newer C# syntax. Switch expressions, using statements, pattern matching, null coalescing statements, etc. By default, we support all syntax supported by the C# compiler.

  • Adding/removing attributes. Note that your code will compile, but System.Reflection won’t pick up on the attribute changes.

  • Use of nullable anywhere

  • Adding new methods

  • Adding, editing, deleting parameters in methods

  • Changing the return type of any method. Includes instance, static, properties, events, indexers, generics, etc.

  • Changing accessibility, E.g. changing a method from private to public

  • Static keyword changes, eg making a method static

  • Renaming methods

  • Editing generic methods just like normal methods

  • Adding/editing/deleting generic parameters

  • Adding/editing/deleting the constraint clause of a generic method (E.g. where T : class, new())

  • Adding/replacing/deleting ref, out, in modifiers on arguments

  • Editing code marked with [BurstCompile]

  • Attaching a debugger to modified code in the Unity Editor, including burst compiled code

  • Attaching a debugger to a Unity Player (On-Device). Supports all code edits just like in the Unity Editor

  • Partial coroutine support - changes do apply to newly created coroutines, but ongoing ones won't update yet

Reacting to Hot Reload patches

Hot Reload can invoke your function when a new patch is applied. There are two attributes that allow your function to be invoked on Hot Reload patches:

InvokeOnHotReload attribute

Methods with this attribute will be invoked whenever any function is patched (or a new function is added):

static class MyStaticClass {
  // Edit MyMethod to invoke HandleMethodPatches
  static void MyMethod() {
    Debug.Log("Current time is: " + DateTime.Now);
  }
 
  [InvokeOnHotReload]
  static void HandleMethodPatches(List<MethodPatch> patches) { // patches parameter is optional
      foreach (MethodPatch methodPatch in patches) {
          Debug.Log($"Received patch for method: {methodPatch.newMethod.Name}");
      }
  }
}

Instance methods are also supported:

public class MyMonobehaviourClass : MonoBehaviour {
  // Edit MyMethod to invoke HandleMethodPatches
  void MyMethod() {
    Debug.Log("Current time is: " + DateTime.Now);
  }
 
  [InvokeOnHotReload]
  void HandleMethodPatches(List<MethodPatch> patches) { // patches parameter is optional
      foreach (MethodPatch methodPatch in patches) {
          Debug.Log($"Received patch for method: {methodPatch.newMethod.Name}");
      }
  }
}

MethodPatch is a class that contains:

  • Original method: Compiled by the Unity Editor. Null for newly added methods.
  • Previous method: Method before Hot Reload applied its patch. Null for newly added methods.
  • New method: Method generated by Hot Reload.

Function removals do not invoke methods with InvokeOnHotReload. Changing function names acts as a removal of the previous method and an addition of a new one.

After a domain reload, such as going from editmode to playmode, Hot Reload re-applies all your changes to the new domain. As a result, InvokeOnHotReload will be called with all of the patches applied before the domain reload.

InvokeOnHotReloadLocal attribute

Methods with this attribute will be invoked when the method itself gets modified. Similar to InvokeOnHotReload, this attribute can be added to both instance and static methods in any class.

[InvokeOnHotReloadLocal]
static void MyMethod() {
  // change the string below to receive the log
  Debug.Log("MyMethod got invoked");
}

Features on the Roadmap

If you’re using or considering a Business license, and one of these is very important to you, let us know and we’ll prioritize it.

  • Adding, editing, removing fields
  • Adding new classes/structs
  • Adding, editing, removing constructors of structs
  • Adding/editing enums
  • Editing generic class methods
  • Editing variable initializers in partial types
  • Editing a method with return type dynamic, or one of the arguments using dynamic
  • Editing a method body with anonymous types
  • Adding or removing one of the following method keywords: partial, abstract, virtual, override, extern
  • Deleting the constructor of a class doesn't remove the constructor logic. As a workaround, consider leaving an empty constructor instead of deleting it, and maybe delete the constructor on the next full recompile.
  • Async method that are already executing are not patched - only new invocations will use the updated logic
  • Supporting editing code dynamically generated by libraries like Unity Multiplayer hl-api, Photon, Bolt, Mirror
  • Adding C# files
  • Applying changes to ongoing coroutines

Always Requires a Full Recompile

  • Adding, modifying, deleting .asmdef files. Note that scripts inside assembly definitions are supported as you’d expect, only modifications to the .asmdef file itself require a full recompile
  • Modifying define symbols, or other things in .csproj or .sln files

Copyright © 2023 Hot Reload for Unity