This is a mod for KSP that allows you to hot-reload DLLs while the game is running. Use it to quickly iterate on your mod during development without needing to restart the game every time you want to make a change.
HotReload will automatically reload any of the following:
- Part Modules
- Vessel Modules
- Scenario Modules
- MonoBehaviour Components
Anything beyond that will not be reloaded and will need to be implemented manually by the mod being reloaded.
To avoid breaking mods and to keep the menu manageable hot-reloading is opt-in.
You can opt-in by adding a custom AssemblyMetadata attribute to your assembly,
like this:
using System.Reflection;
[assembly: AssemblyMetadata("HotReload", "true")]You can also declare this directly in your csproj file
<ItemGroup>
<AssemblyMetadata Include="HotReload" Value="true" />
</ItemGroup>How a reload works depends on its type. Stuff that can use KSP's save/load system should be much more reliable, the way that MonoBehaviours are reloaded will likely lead to some jank.
How these work is pretty straightforward:
- the old version of the module gets saved to a
ConfigNode, - the old version of the module is then destroyed,
- the new version of the module is then added back to the game object,
- the new version reloads its state from the config node in step 1.
This should work pretty much exactly like a scene switch. I expect most vessel and scenario modules to be compatible.
Part modules are more complicated. KSP compiles part prefabs at load time and then new parts are instantiated from that. HotReload attempts to mimic that.
The workflow for part modules is:
- All live part modules from the old assembly are saved and destroyed.
- All part module prefabs from the old assembly are destroyed.
- New part module prefabs are then created for the new assembly.
- The new part modules are then instantiated from the prefab onto the part, loaded, and injected back to their original location in the module list.
KSPAddons and other UI MonoBehavior components are trickier to make work. There's no way to serialize their state in a way that will work most components. This means that hot-reload support for them is a bit more limited.
Here's how hot-reloading a MonoBehavior works:
- The game object containing the MonoBehavior is first disabled.
- Corresponding MonoBehaviors from the new assembly are copied over.
- Fields on the old object are copied over to the new one as long as they do
have types from the assembly being reloaded. This means that a field of type
Twill be left as default ifTis from the assembly being reloaded. The same applies toList<T>. - Any references to other components that are being reloaded are updated to instead point at the new component being loaded in.
OnHotLoadis called on the new component, if it has a method with this signature:void OnHotLoad(MonoBehavior old);
OnHotUnloadis then called on the old component, if it has a method with this signature:void OnHotUnload(MonoBehavior new);
- The old component is then re-enabled and destroyed.
- The new component is now re-enabled.
In short:
- All fields with types defined in other assemblies are copied over by default.
- Any references to other MonoBehaviors defined in the same assembly (and so are also being hot-reloaded) will be automatically updated to point at the new version.
- All other fields will be left as their default value.
- You can implement
OnHotLoadorOnHotUnloadto manually copy state over if you have more complicated needs.
You can define any of the following static methods:
// Called on types in the new assembly being loaded in.
static void OnHotLoad(Assembly old, Assembly new);
// Called on types in the old assembly that is being replaced.
static void OnHotUnload(Assembly old, Assembly new);They will be called in the middle of MonoBehavior reload.
If you need to do things when other assemblies are reloaded then you can add
a listener to HotReload.OnAssemblyHotReload and then drive whatever you want
to reload in your own codebase.
- Global state is not transferred. If you have something that needs to be
carried over then you will need to implement that yourself using
OnHotLoad/OnHotUnload. - Other assemblies will continue to use the original loaded assembly. This applies even if those other assemblies are then reloaded themselves.
- Automatic field copying for arbitrary
MonoBehaviors is limited. For anything complex you will need to useOnHotLoad/OnHotUnload.
HotReloadKSP is available under the MIT license.