Hotloading - s&box Documentation
Hotloading
Whenever you save a code file in your project (.cs or .razor files), we recompile and attempt to live-reload the changed assembly. This lets you quickly iterate and see your changes without needing to restart the editor. Ideally we want to support this for 99% of code changes without you needing to think about what happens under the hood, but this document will help you investigate cases where things go wrong.
How it Works
If you change any type definitions, we need to explore the heap to find and upgrade any instances of those types. We do a full walk starting at static fields, recursing into instance fields that we think could contain stuff to upgrade.
IL Hotload (Fast Hotload)
If you've only changed the bodies of methods, we can usually just patch in the new instructions without walking the heap. This is almost instant, and won't cause any of the pitfalls mentioned later on in this guide. It's enabled by default, but can be disabled in Editor Settings in the General tab.
Optimization
Walking the heap can be very slow! Here's some tricks to help speed things up. These won't apply to IL hotloads.
Diagnosis
Enter hotload_log 2 in the console to get verbose timing information next time you hotload. This will generate a table describing how long it took to process instances of each type, and the total number of those instances. It's sorted by descending processing time, so the biggest culprit should be at the top.
Arrays
We have a fast path for arrays and lists containing value types, as long as they have no reference typed fields.
public record struct UserStruct( Vector3 Foo, int Bar );
public int[] UserStructArray; // Fast
public string[] StringArray; // Slow
public object[] ObjectArray; // Slow
public Vector3[] VectorArray; // Fast
public UserStruct[] UserStructArray; // FastSkipping
We skip processing instances of a type if it can't possibly contain references to instances of user-defined types in its fields. Hotload can attempt to figure this out automatically, but you can force it to skip a field or entire type using the [SkipHotload] attribute.
You should be very careful with manual skipping. It can cause instances that should have been processed to leak into the post-hotload application state, causing lots of weird errors.
ConVar Persistence
Console variables are automatically persisted across hotloads.