Fast Reload 1.3.3 · User guide
Change C# code while your game keeps playing
Save a script and the new code runs in the same Play session, with your score, enemies and scene exactly where they were. Works in the Unity editor from 2021.3 LTS to Unity 6, on Windows and macOS.
One code change in Unity's Boss Room sample (205 scripts), from saving the file to the new code running.
- Unity
- 2021.3 – 6LTS and Unity 6 editors, tested on Unity 7 alpha
- Editor
- Win · MacWindows 64-bit, macOS on Apple Silicon
- Servers and accounts
- NoneWorks offline. Your code stays on your machine
- Added to your build
- 4 KBOne attribute DLL. Everything else is editor-only
What sets Fast Reload apart
Multiplayer code reloads too
An edited RPC still goes through the network, and a NetworkVariable you add during Play reaches the clients. Tested with a host and a client in two editors, as in the multiplayer video above.
Multiplayer → Burst · Entities · Source generatorsBurst jobs and Entities systems too
Edit a Burst job or an Entities system (ISystem or SystemBase) and it reloads. New component types and systems work during Play too. SystemAPI and IJobEntity code works because the source generators run again on the reloaded file. Jobs you did not change stay Burst-compiled, apart from generic jobs a reloaded script schedules itself. Changed jobs and new systems run as plain C# until the next Unity compile, and the Console names them. Checked by editing Unity's own DOTS samples during Play.
What you can change → Rider · Visual Studio · VS CodeDebug the code you just changed
Breakpoints stop in reloaded code, including the ones you set before saving, with their conditions, hit counts and logpoints. Nothing to configure. In Rider, a breakpoint set after attaching stops once you leave the Rider window (Windows) or after attaching again (Mac).
Debugging → No server · No account · Works offlineImport, click Start, done
The C# compiler ships inside the package. Fast Reload downloads nothing, needs no sign-in or config file, and never contacts a server.
Requirements →Also included
- A typo never costs you the sessionA compile error is refused with the reason in the Console, and the last good code keeps running.
- The values you tune stay putNew fields appear in the Inspector with their initial values, and you can add fields to any class of a file. Change a field's type and its Play value carries over.
- New code really runsAdd a script, an Update, an OnTriggerEnter or a UI click handler during Play and Unity calls it.
- Editor scripts and packagesCustom inspectors, editor windows and package code reload the same way as game scripts.
- Still fast after hoursA save compiles only the files that need it, and reload time stays the same after hundreds of reloads.
- Odin InspectorOdin layouts work with reloaded fields, checked with 115 test cases.
- Your libraries tooCode using UniTask, VContainer, Zenject, DOTween, Addressables, Cinemachine, Timeline and Input System was checked by editing it during Play (Unity 6000.3, Mono).
- The Console names what waitsAttributes, new registrations, a new [Inject] field and a new PlayerInput handler are named in the Console instead of doing nothing without a word.
Try it here
Change a value and save. This is how a live change feels in your project.
Find your way
Quick start
You can make your first live change in about five minutes.
- Import the package. In the Package Manager, open My Assets, find Fast Reload and click Import. Import every file.
- Open the window. Choose Tools > Fast Reload > Fast Reload.
- Start Fast Reload. Click ▶ Start Fast Reload while you are not in Play Mode. The first start prepares the compiler (“Engine is preparing”); its warm-up then goes on in the background, and a script you save meanwhile is applied as soon as it is done.
- Press Play, edit, save. Change a script in your code editor and press Ctrl+S (Cmd+S on Mac). The change runs in the game about a second later.
When you are done, exit Play Mode and click ■ Stop. Unity then compiles your changes the normal way, so your project stays exactly as you wrote it. You can also click Compile next to ● Changed since the last Unity compile to compile without stopping.
Try this first. While the game runs, add Debug.Log("Hello from Fast Reload"); to an Update() method and save. The message starts appearing in the Console without the game stopping.
How it works
Fast Reload compiles only what you saved and swaps the new code into the running game. Unity's own compile waits until you stop.
When you save during Play Mode
- Fast Reload notices the saved file.
- It compiles that file, plus edited files that depend on it, with the C# compiler built into the package. The compile runs beside the game, which keeps running.
- Once every file of the save has compiled, it points the methods of the running game at the new code, all in one step of a few hundredths of a second. Objects, scene, static fields and your game state are not touched.
- New fields get their initial values from your code and appear in the Inspector. New Unity callbacks start being called.
- Methods marked
[InvokeOnFastReload]run.
How long it takes
Usually about a second. In Unity's Boss Room sample (205 scripts), one change took 1.6 s with Fast Reload. Unity's default loop of stopping Play, compiling, reloading the domain and entering Play again took 17.6 s. Reload time stays the same after hundreds of reloads in one Play session. The game does not wait for the compile: only applying the new code holds it, usually 30 to 60 ms.
Play starts faster too
While Fast Reload runs, Play Mode starts without a script reload (Unity's Enter Play Mode Options). Play starts faster, and static fields keep their values between Plays. Your own Enter Play Mode settings come back when you click Stop.
Your files stay the source of truth
When you click Stop, Unity compiles all your changes normally. Fast Reload never changes your scripts on disk.
How is Fast Reload different from Unity's MethodReload?
Unity's MethodReload (the experimental com.unity.pipeline package) reloads the methods you mark with [MethodReload]. We tried version 0.9.1-exp.1 on Unity 6000.3:
- Only marked methods reload. A marked method must be public and return void or IEnumerator; edits to other methods wait for a Unity compile. Fast Reload reloads any method, with no attributes to add.
- With the editor's watch (Project Settings > Pipeline), the edited code runs in an interpreter that supports part of C#: a try/catch was skipped with a warning, and LINQ calls (Where, Select) stopped with an error each time they ran. New fields and new generic methods did not compile. Fast Reload runs your code as compiled C#, adds fields during Play, and keeps them in the Inspector.
- The command-line reload (
script.methodreload reload) runs full C#, but the edited method can only use public members of its class. - Netcode for GameObjects: after a reload, an edited RPC ran where it was called instead of going through the network (a
SendTo.NotMeRPC ran on the host). Fast Reload keeps RPCs going through the network, tested with a host and a client in two editors.
MethodReload can also reload code on a connected development build, including IL2CPP devices, which Fast Reload does not do: Fast Reload works in the editor.
Requirements and installation
Fast Reload works in the Unity editor on Windows and macOS, from Unity 2021.3 LTS to Unity 6, and on Unity 7 alpha. Everything it needs is inside the package.
- Unity
- 2021.3 LTS to Unity 6, Unity 7 alpha
- Editor
- Windows 64-bit, macOS (tested on Apple Silicon). Linux is not supported
- Builds
- Mono and IL2CPP, any render pipeline. Fast Reload runs in the editor only
- Debuggers
- JetBrains Rider, Visual Studio (Windows), Visual Studio Code with the Unity extension
- Odin Inspector
- Optional. Tested with Odin Inspector 3 and 4
- Multiplayer
- Optional. Tested with Netcode for GameObjects 1.11 to 3.1, Mirror 96 and Fish-Net 4.7
- Burst and Entities
- Optional. Tested with Entities 1.4.5 to 1.4.8 and Burst 1.8
- Libraries
- Code using UniTask, VContainer, Zenject, DOTween, Addressables, Cinemachine, Timeline and Input System checked by editing it during Play (Unity 6000.3, Mono)
Runs entirely in your editor
The package contains the C# compiler Fast Reload uses. There is no server to download, no account, no license check and no configuration file, and Fast Reload never sends anything over the network. It works the same offline.
What goes into your builds
Only FastReload.Runtime.dll (4 KB), which holds the [InvokeOnFastReload] attribute. Everything else is editor-only.
Unity 7 alpha. Fast Reload supports Unity 7 alpha and was tested on 7000.0.0a8 (Windows) and 7000.0.0a12 (macOS). Later alpha builds were not tested. There, a generic method called with class-type arguments keeps its previous code until a Unity compile, and the Console says so; in Release, a struct's interface methods can be copied into code generic over the struct before the save, and the Console says so when you edit one (Debug code optimization avoids this). Fish-Net 4.7 does not load on Unity 7 alpha, with or without Fast Reload. C# 14 (-langversion:14 in a csc.rsp) was checked with two test games; put the csc.rsp next to your own .asmdef files, since one in Assets reaches packages and Test Framework 1.9.0 does not compile with C# 14.
Updating from an earlier version
Import the new package over the existing “Fast Reload” folder. You do not need to delete anything first. If your project has Editor/FastReloadInspectorBindings.cs from 1.0, Fast Reload empties it the first time you click Stop: new fields no longer need bindings.
Unity 2023.2 with 1.2.0. If Unity 2023.2 stops responding when it opens a project with Fast Reload 1.2.0, delete Assets/Fast Reload/Editor/CoreClrPlugins/MonoMod.ILHelpers.dll, open the project and import the current version.
Project settings
Fast Reload needs no change to your project settings. Earlier versions asked for “Allow 'unsafe' Code” in Player Settings; 1.3 does not, and you can leave it as your project has it.
macOS
Fast Reload works in the Unity editor on macOS with the same features as on Windows. It was tested on an Apple Silicon Mac with Unity 2021.3, 2022.3, Unity 6 and the Unity 7 alpha 7000.0.0a12. Save with Cmd+S. Intel Macs use the same code but were not tested separately.
Third-party components
Fast Reload includes Roslyn (Microsoft.CodeAnalysis), MonoMod, Mono.Cecil and Iced, all under the MIT License and all editor-only. See Third-Party Notices.txt in the package.
The Fast Reload window
Open it with Tools > Fast Reload > Fast Reload. It starts and stops Fast Reload and shows what happened on the last save.
Buttons and status lines
- ▶ Start Fast Reload
- Starts watching your scripts. Click it outside Play Mode
- Running (top right)
- Fast Reload is active: every save is applied
- ■ Stop
- Stops Fast Reload, restores your Enter Play Mode settings and lets Unity compile your changes. Use it after exiting Play Mode
- ● Changed since the last Unity compile, Compile
- Your scripts changed since Unity last compiled them. Compile runs a normal Unity compile without stopping Fast Reload
- Last reload
- The file that was applied, how many methods changed and how long it took
- ✖ Compile error
- The last save did not compile. The game keeps the previous code. The error is in the Console
- ⚠ and a number (compact mode)
- Changes that need a Unity compile. Click it to see them
- + New script detected, Refresh
- A script was created outside Play Mode. Refresh runs a Unity compile so it can be used
Settings
- Inspector for new fields On
- Shows fields added by a reload, and components of new scripts, in the Inspector
- Run in background Project setting
- Keeps the game running while your code editor has the focus. Turn it on to watch the game while you type
- Show new scripts during Play On
- Shows scripts created during Play in the Project window. Unity compiles them when Play ends
- Reload outside Play Mode On
- Scripts saved outside Play Mode are reloaded too, editor scripts included; Unity compiles them at Stop or with Compile. A new field Unity saves (public or [SerializeField], on a component or ScriptableObject) is compiled by Unity right away, so that the values you set are kept. Off: Unity compiles scripts saved outside Play Mode, as without Fast Reload
- Reload scene on Play Off
- Off: Play starts without reloading open scenes, which is faster. On: scenes reload as usual, for assets that expect a freshly loaded scene
- Debug logs Off
- Prints detailed Fast Reload messages to the Console. Useful when you report a problem
- Compact mode Off
- Shrinks the window to one line for docking above the Scene view
- Packages
- The packages whose scripts are reloaded. Embedded, local, Git and tarball packages always are; tick the registry and built-in packages you want too. Unity keeps those in Library/PackageCache and compiles your edits there, but Package Manager operations can lose them, so embed a package you change a lot
- Advanced > Recompile all edited files Off
- Off: a save compiles the saved file and the edited files that depend on it. On: every file edited in the session, on every save. Slower; turn it on if a file seems to keep an old value
- Advanced > Compile while the game runs On
- On: a save compiles beside the game, which keeps running, and the new code is applied when it is ready. Off: the editor waits for the compile, as in 1.2
What you can change while playing
Almost any code change is applied live. The few that are not are refused with a message, and the game keeps running.
Applied live
- Method bodiesAny logic, including Update, coroutines, event handlers, virtual and override methods. A coroutine or async method already running finishes with the code it started with; the methods it calls and the runs started after the save use the new code
- New, removed and renamed methodsChanged parameters and return types too. Save the scripts that call them, as for a normal compile. A new override of a method or a property also reaches the objects made before the save
- New Unity callbacksUpdate with input, physics, mouse, GUI, animation and UI events. See New Unity callbacks
- New fields and propertiesIncluding auto-properties, with the initial values from your code. Removing fields works too
- New fields on ScriptableObjects and on components with a custom EditorShown in the Inspector, one value per asset for the Play session
- Changing the type of a fieldAlso when other scripts use it: they are compiled again, and the current Play value is kept when it can be converted (int to float, int to string)
- Events and ActionsAdding, subscribing and invoking new C# events and Action fields
- New classes, structs, enums and enum valuesAnd brand-new script files. See New scripts while playing
- Generics, lambdas, LINQ, local functions, switch expressions, pattern matchingGeneric methods and classes are patched per type used. A method using the class's static fields keeps its code until a Unity compile, so that their values stay, and the Console says so. Edits of iterators, async methods and lambdas of generic classes and methods apply too; one that adds or removes their local variables waits for a Unity compile, said in the Console
- Several files saved at onceWith references between them. Files that depend on the saved file are recompiled automatically
- Assembly Definition (asmdef) scriptsNew and renamed members of a class can be used from the other assemblies during Play
- Constants, enum values and default parameter valuesA changed value reaches every script using it, also the ones not saved during Play: Fast Reload compiles them again (above 30 scripts the Console says they wait for a Unity compile). A default value reaches the calls that leave the argument out
- Scripts in packagesEmbedded packages in the Packages folder, local packages (“file:” in Packages/manifest.json), Git and tarball packages, and the registry and built-in packages you choose under Settings > Packages in the Fast Reload window
- Editor scriptsCustom Editors (inspectors), EditorWindows and PropertyDrawers, in Play Mode and outside it. Windows and inspectors already open use the new code
- Burst-compiled codeJobs, Entities systems and function pointers, and the code they call. Until the next Unity compile the changed ones run as plain C#, and the Console names them; the others stay Burst-compiled, also the jobs next to a changed one in the same script. Saved outside Play Mode, a change goes to a Unity compile. Generic jobs a script schedules itself, and [BurstCompile] static methods called from C#, run as plain C# once their script is reloaded, and the Console says so. Checked by editing Unity's own DOTS samples during Play
- New Entities component types and systemsIn a new script or an existing one, during Play: buffers, shared, managed and cleanup components, SystemBase and ISystem with SystemAPI and IJobEntity. They run as plain C# until the next Unity compile. A new system in an existing script starts over from OnCreate when you edit that script. A field added to an ISystem works too, from its default value
- Code that uses source generatorsEntities (SystemAPI, IJobEntity, Entities.ForEach, new and changed queries, Bakers when an open subscene bakes again), UI Toolkit's [UxmlElement] and your own generators run on the reloaded script
- Multiplayer codeNetcode for GameObjects, Mirror and Fish-Net: RPCs still go through the network, and what you add during Play is synchronized. See Multiplayer
- SendMessage, Invoke and InvokeRepeatingCalling methods added during Play
- NamespacesNested and custom namespaces
Scene objects, static fields and singleton instances keep their values across every reload.
Needs a Unity compile
Fast Reload detects these, tells you in the Console and keeps the game running on the previous code. The change applies at the next Unity compile.
- Adding or removing fields in a structA struct's memory layout cannot change while it is in use (Entities components too)
- Changing the type of a field that partial classes declare, or that package DLLs useRefused with the name of the code that uses it
- Adding OnAudioFilterRead, OnRenderImage, OnApplicationPause, OnApplicationFocus or OnApplicationQuitUnity registers these only when a script is compiled
- Scripts of registry and built-in packages you have not chosenChoose them under Settings > Packages in the Fast Reload window
- Fish-Net client-side prediction added to a class that had none[Replicate] and [Reconcile] methods add fields to the class
- An interface added to an existing classIts objects implement it only after a Unity compile, so
isandaschecks would fail: the Console says why (UI event interfaces work) - A new override of a member declared in another assembly, or of an auto-propertyAnother .asmdef, a package or Unity: the objects made before the save keep the base member until a Unity compile, and the Console says so. The empty callbacks of Mirror, Fish-Net and Netcode work at once
- A new [Inject] field (Zenject, VContainer)It stays null on the objects already built, because the container fills it when it builds an object: the Console says so. Objects built after the save get it, and all of them in the next Play
- Serializing a field added during PlayJsonUtility, and serializers reading the class's fields such as Newtonsoft Json, leave it out until a Unity compile
- The name of an enum value added during PlayCode not reloaded with the enum's file prints it as its number (ToString, string interpolation, Enum.GetName, Enum.Parse, Enum.GetValues) until a Unity compile, said in the Console. Comparisons, switch cases and saved values use it at once
- A new handler for PlayerInput's Send MessagesPlayerInput does not call a new On<Action> method until the next Unity compile: the Console says so. A change to a handler it already calls applies
New fields in the Inspector
A field you add during Play Mode appears in the Inspector under Fast Reload Fields, with the initial value from your code, and you can edit it live.
public class HeroStats : MonoBehaviour
{
public int health = 120;
public float critChance = 0.25f; // added while playing
public Color trailColor = Color.red; // added while playing
}After you save, Crit Chance and Trail Color appear at the bottom of the HeroStats component. Changing them in the Inspector changes what the running code reads, immediately.
Where new fields appear
- Unity's default Inspector
- A Fast Reload Fields section at the bottom of the component
- Components with your own custom Editor
- Your editor keeps its look; the section is added below it
- ScriptableObject assets
- In the asset's Inspector; each asset keeps its own value
- Odin Inspector
- In the Odin layout, with attributes such as Range, BoxGroup, ShowIf and LabelText, and new buttons
Supported field types
Numbers, bool, string, enums, Vector2/3/4, Color, Rect, Bounds, Quaternion, references to Unity objects, and lists and dictionaries of these. [Header] and [Space] on new fields are shown.
Undo and Redo
Every edit of a new field can be undone with Ctrl+Z and redone with Ctrl+Y (Cmd+Z and Cmd+Shift+Z on Mac), also in Odin Inspector.
How long values last
Values last for the Play session. Scene and asset files keep their original layout until Unity compiles the change. After that compile the field is a normal field and starts from the initial value in your code, so copy a value you tuned into the script.
To hide the section, turn off Inspector for new fields in the Fast Reload window.
New scripts while playing
Create a new .cs file during Play Mode and use it right away. Unity compiles it normally when Play ends.
- Create the file in your code editor or in the Project window, and save it.
- Fast Reload loads it on save. The Console shows “New script … loaded without a Unity compile”.
- Use the new class from other scripts as usual, and save those scripts too.
Putting a new MonoBehaviour on a GameObject
Unity does not know the new script until it compiles it, so use one of these instead of Add Component:
- GameObject > Fast Reload > Add New Script Component with the object selected
- Add New Script Component (Fast Reload) at the bottom of the Inspector
- Add to selection next to the script in the Fast Reload window, or drag the script's row onto the Inspector, the Scene view or the Hierarchy
When Play ends
Unity compiles the new scripts. Components you added this way are put back on their objects after that compile, with their values. Save the scene to keep them.
A script you create outside Play Mode is compiled by Unity as usual: the window shows “+ New script detected” with a Refresh button that starts that compile.
New Unity callbacks
Add a Unity message method during Play Mode and Unity calls it like any other, in its usual order.
- Player loop
- Update, LateUpdate and FixedUpdate run in Unity's player loop, in Unity's order, and input works in them
- Physics
- OnTriggerEnter/Stay/Exit and OnCollisionEnter/Stay/Exit (3D and 2D), OnControllerColliderHit, OnJointBreak
- Mouse, GUI and rendering
- The OnMouse events, OnGUI, OnDrawGizmos, OnBecameVisible/Invisible
- Animation, hierarchy, particles
- OnAnimatorMove/IK, OnTransformParentChanged/ChildrenChanged, the particle callbacks, OnDestroy
- UI events
- IPointerClickHandler, IDragHandler and the other EventSystems interfaces added to a component
Objects created later
Objects created after a reload (Instantiate, AddComponent, scene loads, the next Play) run the methods added during Play Mode, starting with Awake, OnEnable and Start.
Callbacks that need a Unity compile
OnAudioFilterRead, OnRenderImage, OnApplicationPause, OnApplicationFocus and OnApplicationQuit added during Play apply at the next Unity compile.
Run code after a reload
Mark a method with [InvokeOnFastReload] and it runs right after every reload, while the game keeps running.
Use it to spawn something you just wrote, rebuild a level, connect a new field or event to existing objects, or reset a test. It runs after every reload, so guard it to do its work once:
[InvokeOnFastReload]
void SpawnBoss()
{
if (units.Exists(u => u.name == "Boss")) return; // only once
var boss = Instantiate(bossPrefab, new Vector3(-3, 0, 0), Quaternion.identity);
boss.name = "Boss";
}The attribute lives in FastReload.Runtime.dll, so this code also compiles in builds, where it simply never runs.
Re-run start-up code
Awake, OnEnable and Start ran once, when Play began. After you change them, run them again with the new code:
- GameObject > Fast Reload > Re-run Start-up of All Components on the selected objects
- Right-click a component header and choose Fast Reload: Re-run Awake, OnEnable, Start, or Fast Reload: Re-run Start for Start alone
Debugging reloaded code
Attach your debugger to the Unity editor as usual. Breakpoints stop in the code Fast Reload reloaded, also the ones you set before the reload, with the call stack, variables, watches and stepping.
Set up your IDE
- JetBrains Rider
- Nothing to set up: Run > Attach to Unity Process. A breakpoint set before you attach stops in reloaded code right after every save. On Windows, one set after attaching stops there once you leave the Rider window: within about 30 seconds, or at once when you come back to Rider; while Rider stays in front it stays in the old code. For this Fast Reload changes the reloaded script's modified time (never its text) while Rider is away. On a Mac, stop debugging and attach again. With Rider as the script editor, the Console says this once per Play. At a stop in reloaded code Rider may say "The source file may have changed since building the module": the lines are right. Fields of the current object show under
thisin the Variables view - Visual Studio (Windows)
- Nothing to set up. Fast Reload reads your breakpoints from Visual Studio while it runs
- Visual Studio Code
- Nothing to set up. With VS Code as the script editor (Preferences > External Tools), Fast Reload adds its small extension, which hands your breakpoints over, the first time it starts. If you remove it, Tools > Fast Reload > Add Extension to VS Code adds it again
What works in reloaded code
- Breakpoints set before the reloadThey stop in the new code, also after you added lines above them
- Call stack, variables, watches, Step Over, Step IntoAs in any debugging session. While a breakpoint holds the game, the editor waits
- Conditions and hit counts“Is true”, Visual Studio's “when changed”, and hit counts in Visual Studio
- Logpoints and tracepointsThe message goes to the debugger's output and the code runs on, with
{expressions}and Visual Studio's$FUNCTION,$CALLER,$CALLSTACKand the other tokens - Function breakpointsBy method name, also for methods added during Play
- Breakpoints on expression-bodied members (
=>) - Edit while pausedSave while the debugger holds the game: after one Continue the next call runs the new code, and breakpoints you removed no longer stop
- Correct file and line numbersExceptions and Debug.Log stack traces in the Console point at the line you edited
Good to know
- In Visual Studio and VS Code a stop in reloaded code shows as a pause rather than a breakpoint hit. Variables, call stack and stepping are the same.
- A breakpoint you set or remove during Play applies to reloaded code about a second later, when Fast Reload reloads that file.
- Fast Reload compiles a condition or message into the code at the breakpoint. One that cannot compile there, for example one that names a variable declared on that very line, gets a warning in the Console and that breakpoint does not stop.
- Fields added during Play do not show under
this, because Fast Reload keeps them next to the object. Put one in a local variable to see it. - With Visual Studio or VS Code, Fast Reload writes the reloaded code to
Library/FastReload/Loadedso their debugger can step through it. The files are removed the next time Fast Reload starts. - For exact line numbers in exceptions, debug with Unity in Debug mode (the bug icon at the bottom right of the editor). In Release mode Mono reports lines only approximately, also for code Unity compiled.
Multiplayer
With Netcode for GameObjects, Mirror or Fish-Net, multiplayer scripts reload like the others: an edited RPC still goes through the network, and what you add during Play reaches the other side.
These packages write the networking code into your scripts when Unity compiles them (their IL post-processor, or weaver). Fast Reload runs that weaver on the scripts it reloads, so the reloaded code sends and receives as the compiled code does.
What applies live
- Edited RPCs and commandsNGO's Rpc, ServerRpc and ClientRpc, Mirror's Command, ClientRpc and TargetRpc, Fish-Net's ServerRpc, ObserversRpc and TargetRpc, and the code they call
- RPCs added during PlayAnywhere in the class, also in a base class whose subclasses have RPCs of their own
- Synced variables added during PlayNetworkVariable and NetworkList; SyncVar with its hook, SyncList, SyncDictionary and SyncSet; Fish-Net's SyncVar<T> and SyncList<T>. From the server, and from the owner's client for those it writes
- Objects spawned later, and subclassesObjects spawned after the reload and objects of subclasses get what you added too
- Fish-Net client-side predictionEdited [Replicate] and [Reconcile] methods run their new code on the server and on the clients
- Your own structs and enumsDeclared in the reloaded script and used as RPC arguments or synced values, also in a synced variable you add during Play
Testing with two editors
To see a change on the host and a client at once, run them in two editors that share your scripts. Two tools make the second editor: ParrelSync (free, Unity 2021.3 and later) and Unity's Multiplayer Play Mode (Unity 6). Fast Reload runs in the second editor by itself: you start and stop it in the main editor only.
With ParrelSync
- Install ParrelSync. In the Package Manager, click + > Add package from git URL and enter
https://github.com/VeriorPies/ParrelSync.git?path=/ParrelSync. - Make a clone. Choose ParrelSync > Clones Manager, click Create new clone, then Open in New Editor. The clone is a second project linked to your Assets, Packages and ProjectSettings, so a script you save is saved for both.
- Start Fast Reload in the main editor. The clone's editor starts and stops Fast Reload with it.
- Press Play in both editors, then start the host in one and a client in the other.
- Edit and save as usual. Both editors reload the change and keep talking.
With Multiplayer Play Mode
- Install it. In the Package Manager, install Multiplayer Play Mode (com.unity.multiplayer.playmode).
- Turn on a player. Choose Window > Multiplayer > Multiplayer Play Mode and tick Player 2.
- Start Fast Reload in the main editor. A player has no Fast Reload window: Fast Reload runs in it while the main editor's runs.
- Press Play in the main editor. The players enter Play with it; start the host and the client as your game does.
- Edit and save. The main editor and the players reload the change.
A built player as the client keeps the code it was built with. Code the host runs, such as a ServerRpc's body, still changes for it; code the client runs, and RPCs or synced variables you add, need a new build.
public class Turret : NetworkBehaviour
{
// Added during Play: the clients get it, also on turrets spawned later
public NetworkVariable<int> Heat = new NetworkVariable<int>();
[Rpc(SendTo.Server)]
void FireServerRpc(Vector3 aim) // edited during Play: still sent to the server
{
Heat.Value += 10;
SpawnBullet(aim);
}
}Tested with
- Netcode for GameObjects 1.11, 2.x and 3.1, Mirror 96 and Fish-Net 4.7
- Unity 2021.3, 2022.3, 6000.3 and 6000.7, on Windows and macOS; Unity 7 alpha with Netcode for GameObjects and Mirror
- ParrelSync 1.5.3 clones, and Multiplayer Play Mode 2.0 players on Unity 6.3
- Unity's Boss Room and Bitesize samples and the Mirror and Fish-Net demos, edited during Play in two editors
Good to know
- Start and stop Fast Reload in the main editor: ParrelSync clones and Multiplayer Play Mode players follow it. An editor that does not run Fast Reload keeps its previous code, and the two sides disagree until both have the same code.
- The two editors reload a save a moment apart. Right after you add a synced variable, the other side can log one warning (Netcode for GameObjects: an OverflowException; Fish-Net: “received a sync type it does not have”). The values match again once both have reloaded.
- Fish-Net keeps its list of network prefabs in an asset: after you add a network prefab, refresh the clone once (Assets > Refresh).
- The first reload of a networked script takes about as long as the next ones: Fast Reload warms up the weaver when it starts.
- Adding client-side prediction ([Replicate] and [Reconcile]) to a Fish-Net class that had none needs a Unity compile.
- Photon (PUN 2, Fusion) and Netcode for Entities are not supported.
Errors and refused changes
Nothing you save can break Play Mode. A compile error or an unsafe change leaves the game running the last code that worked.
A compile error
The Console shows [FastReload] Compile Fail and the C# error with its file and line, for example error CS0103: The name 'damge' does not exist in the current context. The window shows ✖ Compile error and the game keeps running the previous code. Fix the error and save again.
A change that needs a Unity compile
Some changes cannot be applied safely while the game runs (see What you can change). Fast Reload refuses them with a yellow warning that names the reason, and applies nothing from that file.
- HitInfo: instance field added (normal). Its code is not hot-patched (it keeps the previous code); a Unity compile applies itA struct gained a field: its layout cannot change while it is in use
- Changing the type of existing field 'score' (System.Int32 -> System.Single) requires a full compile: …A partial class declares that field, or a package DLL uses it
- … Fast Reload unavailable (its base class … is internal to its assembly, and a reloaded copy is another assembly)The class derives from an internal class in another assembly
Keep playing; your other changes still apply. When you want the refused change, exit Play Mode and click Compile in the Fast Reload window, or ■ Stop. In compact mode the number next to ⚠ counts these warnings.
Troubleshooting
Most problems come from Fast Reload not running, or from a change that needs a Unity compile.
Nothing happens when I save
- Cause
- Fast Reload is not running
- Fix
- Open the window. If it shows ▶ Start Fast Reload, exit Play Mode, click Start, then press Play
- Cause
- The script is in a registry or built-in package you have not chosen
- Fix
- Tick the package under Settings > Packages in the Fast Reload window
An “Engine is preparing” popup
- Cause
- The compiler is being prepared after the first start
- Fix
- Nothing to do: it closes by itself, and the rest of the warm-up runs in the background
A yellow warning, and the change is not applied
- Cause
- The change needs a Unity compile
- Fix
- See Errors and refused changes
A Burst warning: “not a known Burst entry point”
- Message
Compilation was requested for method … but it is not a known Burst entry point, in the Console after you save a script with Burst jobs- Cause
- The reloaded job is a new copy of your code, and Burst knows only the code Unity compiled, so that job runs as plain C#. Only a job you changed runs this way, and Fast Reload's own warning names it once per Play
- Fix
- Your code runs correctly and your change applies, only slower. After the next Unity compile your jobs are Burst-compiled again, so press Compile now in the Fast Reload window before you measure Burst's speed
“… creates a query during OnUpdate” after a new SystemAPI query
- Cause
- A reloaded system builds a query added during Play the first time it runs, because its OnCreate ran before the query existed
- Fix
- Nothing to do: this is expected and harmless. After the next Unity compile the query is built in OnCreate as usual
“Import Error Code:(4)” after a save with a subscene open
- Message
Build asset version error: … in SourceAssetDB has modification time …(seen on Unity 6000.7)- Cause
- While Fast Reload runs, Unity imports a saved script only at the next Unity compile, and a background bake of the subscene noticed the newer file
- Fix
- Nothing to do: this is harmless. Your change applies, and the message goes away after the next Unity compile
A new field is not in the Inspector
- Cause
- Inspector for new fields is off
- Fix
- Turn it on in the Fast Reload window
A changed value looks old in another script
- Cause
- That script was not recompiled
- Fix
- Save that script too, or turn on Recompile all edited files
Static fields keep values from the last Play
- Cause
- Play starts without a domain reload while Fast Reload runs
- Fix
- Reset them in code (see Tips), or click Stop
The game pauses while I type
- Cause
- Run in background is off
- Fix
- Turn on Run in background in the Fast Reload window
A breakpoint does not stop in reloaded code
- Cause
- VS Code: the Fast Reload extension was removed
- Fix
- Choose Tools > Fast Reload > Add Extension to VS Code
- Cause
- Its condition or message cannot compile at that line
- Fix
- Read the warning in the Console and change the condition
Exception line numbers are slightly off
- Cause
- Unity is in Release code optimization
- Fix
- Switch to Debug mode with the bug icon at the bottom right of the editor
Multiplayer: the other editor does not get what I added
- Cause
- Fast Reload does not run in that editor, so it kept its previous code
- Fix
- Start Fast Reload in the main editor: ParrelSync clones and Multiplayer Play Mode players follow it. A clone's Fast Reload window then shows Running (see Multiplayer)
- Cause
- The client is a built player
- Fix
- Build again, or test with a second editor: a build keeps the code it was built with
Unity compiles for a while after Stop
- Cause
- Stop starts the normal Unity compile of your changes
- Fix
- Expected: it is the compile Fast Reload saved you during Play
OverflowException on the client while both editors reload
- Cause
- The two editors reload a save a moment apart; an update sent in between does not match a NetworkVariable just added
- Fix
- None needed: once both editors have reloaded, Fast Reload sends the object's values again
Unity 2023.2 stops responding with Fast Reload 1.2.0
- Cause
- Two MonoMod libraries in 1.2.0 refer to each other, and Unity 2023.2 runs out of memory
- Fix
- Delete
Assets/Fast Reload/Editor/CoreClrPlugins/MonoMod.ILHelpers.dll, open the project and import the current version
Auto Refresh is Disabled in Preferences after Fast Reload 1.3.0 or earlier
- Cause
- Those versions turned it off while running, and Unity can save Disabled when it starts, or an Asset Pipeline preference is changed, while it is off
- Fix
- Set it back in Preferences > Asset Pipeline > Auto Refresh
Still stuck? Turn on Debug logs, reproduce the problem, and send the Console output to support.
Tips
Small habits that keep long Play sessions smooth.
Watch the game while you type
Turn on Run in background in the Fast Reload window. Without it, Unity may pause the game while your code editor has the focus.
Tune in the Inspector, then copy into code
New-field values last for the Play session. When a number feels right, write it into the field's initializer so it survives the next Unity compile.
Static fields keep their values between Plays
While Fast Reload runs, Play starts without a domain reload. If your code expects statics to start fresh on every Play, reset them in a method marked [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)], or click Stop.
Unity 6 Input System
If input stops working after Play starts without a domain reload, enable your action map in Start():
void Start()
{
var input = GetComponent<PlayerInput>();
if (input != null && input.actions != null)
{
if (input.currentActionMap == null) input.currentActionMap = input.actions.actionMaps[0];
input.currentActionMap.Enable();
}
}Release and Debug code optimization
Both work. In Release (Unity's default), Mono can copy a small method into the code that calls it, so a later edit would not reach that code. Fast Reload keeps your scripts' methods from being copied this way in the editor. A call of a small method then costs about a nanosecond more in the editor; player builds are not affected. On Unity's CoreCLR (Unity 7000 alpha) in Release a small method can still be copied into code compiled before the save, in two cases: a struct's interface method where code generic over the struct calls it (a comparison in List.Sort or OrderBy, a Dictionary key, a job's Execute run without Burst), which the Console says when you edit one, and a generic method or a generic class's method reached only through other generic code. Debug code optimization avoids this.
Compile when you take a break
Clicking Compile or Stop now and then keeps Unity's own build of your scripts in step with your edits.
Odin Inspector
Fast Reload does not need Odin. When Odin is installed, what you add in Play Mode also appears in Odin inspectors.
- New fields with their attributesRange, LabelText, BoxGroup, FoldoutGroup, TabGroup, ShowIf, HideIf, OnValueChanged, ValueDropdown, ReadOnly and others
- New
[Button]methodsIncluding buttons with parameters and return values - Attributes added to existing fields
- SerializedMonoBehaviour fieldsSuch as Dictionary
- Undo and RedoFor edits of fields added during Play
This was checked with 115 test cases on Odin Inspector 3 and Odin Inspector 4. Classes that inherit from Odin's editor classes (OdinEditor, OdinEditorWindow) reload like your other editor scripts.
Release notes
Each version includes everything before it.
1.3.3
Current version
New
- A property override added during Play reaches the objects made before the save, as an added method override does.
- Supports C# 14 on Unity 7 alpha (turned on with
-langversion:14in a csc.rsp), checked with language tests and two test games. A few cases need a Unity compile; see Requirements and installation.
Stability update
More kinds of edits reload correctly during Play. Before, these kept the previous code or failed to compile:
- Iterators and lambdas in generic classes and generic methods
- Explicit interface implementations, default and static interface methods
- Changed constants, enum values and default parameter values, also in scripts you did not save
- Members added or renamed during Play, used from another .asmdef
TryGetComponenton reloaded scripts, and removed overrides- Unity 7 alpha:
fieldproperties, type aliases, primary constructors, generic classes in Release, andReverse()in editor scripts
1.3.2
New
- Supports Unity 7 alpha, tested on 7000.0.0a8 (Windows) and 7000.0.0a12 (macOS): methods of structs reload, which includes every Entities ISystem, and new Entities types work during Play with its built-in Entities 6.7. Netcode for GameObjects and Mirror were tested with two editors. Fish-Net 4.7 does not load on Unity 7 alpha, with or without Fast Reload.
- A coroutine or async method edited during Play: the Console says that a run already going keeps its code.
Fixed
- Objects a class makes of itself in reloaded code (new Timer() inside Timer, a clone, a singleton) are of the class your compiled code knows: they go into its static List, array or Dictionary, where they threw ArrayTypeMismatchException. A private nested class kept in its outer class's List works the same way.
- is, as, casts, switch, foreach and catch on a class's or struct's own type in reloaded code find objects made before the save. They were false or threw, so an Equals(object) told no two objects equal.
- A struct's static fields are shared with compiled code after a save; before, reloaded code had a copy of its own. An edited static readonly initializer reaches reloaded code.
- A file with var copy = this; in a struct next to a class, or a class implementing IEnumerable of itself, reloads; before, any edit failed to compile.
- A new Entities system taken out of its file during Play is removed from the running game at that save.
1.3.1
New
- New Entities component types and systems work during Play without a Unity compile, in a new script or an existing one, and a field added to an ISystem works too. They run as plain C# until the next Unity compile.
- Jobs you did not change stay Burst-compiled when their script is reloaded, and the Console names every job that runs as plain C#.
- New fields work on any class of a file, such as a [Serializable] data class next to your MonoBehaviour, not only on its main class.
- Checked by editing code during Play that uses UniTask, VContainer, Zenject, DOTween, Addressables, Cinemachine, Timeline and Input System (Unity 6000.3, Mono).
Fixed: files that could not be reloaded
- A file with a nested class that has a method named as a Unity callback (Update, Start and the like), and a class with a static array or List of its own type (uGUI's Selectable has one): before, any edit failed to compile.
- A call that only an internal method of another assembly makes ambiguous, like Mesh.bounds.ToAABB() with Unity.Mathematics and URP's namespace.
- A class with two indexers, and a class that overloads a callback's name (Update() and Update(float)).
- A file declaring State, State<T> and State<T,U> is no longer refused for a field type change it did not make.
Fixed: changes that did not apply as expected
- Types declared next to the code using them stay the same types for code keyed by Type: an event bus or Zenject's signals keep delivering after a save, and calls through an interface of the same file no longer fail on CoreCLR.
- A generic class with static fields keeps their values when its file is saved: an EventBus<T> keeps its subscribers and a pool its items. The methods using those fields keep their code until a Unity compile, and the Console says so.
- Release code optimization on Mono: edits of small methods in generic classes now apply.
- A field renamed during Play with [FormerlySerializedAs] keeps its current value.
- A lambda that stops using "this" runs its new code also in delegates created before the save. One that starts using "this" keeps the old code, and the Console says so.
Fixed: speed and messages
- The first save of a file with something generic no longer stops the game for seconds.
- Attributes and new registrations ([ContextMenu], [Range], [MenuItem], [CustomEditor] and the like) no longer do nothing without a word: the Console names them. Saved outside Play Mode, Unity compiles them right away, and so does a change Fast Reload refuses there.
- The Console says when a new [Inject] field stays null on existing objects, when PlayerInput does not call a new handler, and why an interface added to a class is refused.
- Compile now restarts Fast Reload also when there is nothing to compile.
- Unity 6000.7: the "IgnoresAccessChecksToAttribute: instance field removed" lines no longer appear. A generic method you did not change no longer gets a "Fast Reload unavailable" notice (Unity Code Optimization set to Debug).
Fixed: editor and debugger
- An editor closed or crashed while Fast Reload ran, opened again with no Fast Reload window open, could stop responding on a later save; Fast Reload now starts stopped there.
- Fast Reload no longer writes Unity's Auto Refresh setting, which is shared by every Unity on the PC: closing Unity with Fast Reload on no longer leaves it off for other projects. If Preferences > Asset Pipeline still shows Auto Refresh as Disabled after an earlier version, set it back there.
- Rider stops at breakpoints in reloaded code after every save when they were set before attaching (before, it could miss them). On Windows, one set after attaching stops there too once you leave the Rider window; on a Mac it needs attaching again. The Console says which.
Updating from any earlier version: import over the existing "Fast Reload" folder. No manual cleanup needed.
1.3.0
- The game keeps running while a save compiles (before, it stood still for the whole compile: several seconds for a networked script); applying the new code takes a few hundredths of a second
- Debugging reloaded code in Rider, Visual Studio and Visual Studio Code: breakpoints stop in reloaded code, also those set before the reload, with conditions, hit counts, logpoints and function breakpoints
- File and line numbers of your scripts in stack traces and the Console
- Scripts in packages are hot reloaded: embedded, local, Git and tarball packages, and the registry and built-in packages you choose
- Editor scripts are hot reloaded, in Play Mode and outside it: custom Editors, EditorWindows and PropertyDrawers
- Burst-compiled code: a change to a job, an Entities system or a function pointer applies (checked on Unity's DOTS samples)
- Source generators run on reloaded scripts: Entities, [UxmlElement] and your own generators
- Multiplayer (Netcode for GameObjects, Mirror, Fish-Net): RPCs still go through the network, also new ones; synced variables and collections added during Play are synchronized; Fish-Net's client-side prediction reloads; a Multiplayer Play Mode player reloads too, following the main editor's Fast Reload
- Unity callbacks added during Play run: Update with input, physics, mouse, GUI, UI events and more, also on objects created after the reload
- A changed constant updates the scripts of other assemblies that use it
- Release code optimization: edits of small methods always apply
- Unity 2023.2 no longer runs out of memory when it loads Fast Reload
- Unity 2021.3 LTS supported
- A ParrelSync clone follows the original editor's Start and Stop reliably, and a Multiplayer Play Mode player the main editor's; a clone saves no assets (no blocked-save dialog at each Stop)
- NetworkVariables added during Play: Unity structs (Color, Vector3) and FixedStrings sync too, and the values sent while the editors reload are sent again
- An interface added during Play to an existing class is refused with the reason (before,
ischecks failed without a word) - Fixes: an existing script saved together with new scripts, two scripts with the same file name, a property named like its type, new fields of an enum type, [Header] and [Space] on new fields, a static field of an enum or struct of its own class, setting a member of a static struct field, [InvokeOnFastReload] in a new script on its first load, fields added with an array initializer, a singleton's static auto-property read by reloaded code, a field added to an existing declaration, a static field of a project type in a file's second class, an editor's safe save (its temporary file was imported), scripts of a project with Unity's Code Coverage package, a method taking its own class subscribed to an event or passed as an argument,
nameof(Type.Member)after a type of the same name in another namespace was reloaded
1.2.0
- macOS support, tested on Apple Silicon
- New fields on components with a custom Editor and on ScriptableObjects
- Changing the type of a field that other scripts use, keeping the Play value
- Undo and Redo for new-field edits, also in Odin Inspector
- Reload time no longer grows in long sessions
- Fixes for saving several files at once, nested types of base classes, partial classes, out arguments and arrays
1.1.0
Not released separately
- New scripts while playing, and new fields in the Inspector, also with Odin
- Optional Odin Inspector support
- Assembly Definition support with automatic recompile of dependent files
- SendMessage, Invoke and InvokeRepeating with new methods
- Re-run Start-up and Add New Script Component menus
- Generic classes and auto-properties
- Unsafe changes refused with a clear message; the Inspector bindings file is no longer needed
1.0.4
- Fixes for override Unity callbacks and relative namespaces in inherited classes
1.02
- Odin Inspector layout compatibility, new files visible in Play Mode, initial values of new fields in the Inspector
Support
Write to us by email. A person who works on Fast Reload answers.
What to include
- Your Unity version and operating system
- Your code editor or debugger, if the problem is about debugging
- The Console output with Debug logs turned on in the Fast Reload window