So, if you're just here to read about game news, skip ahead.
A cool feature in Unity is that you can update your C# scripts while your game is already running. Unity will reload the scripts, and you can test them out on the spot, make some more changes, test again, etc., all without ever stopping and restarting your game. People call this sort of thing "hot reloading" or "hot deployment."
It makes for a great, productive, efficient workflow.
Unfortunately, if you're using the otherwise-amazing Rewired asset to manage your game's input, that feature becomes broken. At least by default.
Through some trial and error, I found a way to make it work. Here's how. This is partially documented in Rewired's own documentation, but that solution is incomplete (as was everything else I found online about it), hence my posting here.
1. Update your polling code to check ReInput.isReady before you check any input. Respawn the Rewired Input Manager if a recompile recently took place
Rewired's documentation describes part of this process. They mention that you should call ReInput.isReady (note: ReInput, not Rewired) to check whether Rewired is ready for use, and that you shouldn't make any calls to any of the button/axis polling methods if isReady is false.But I found that isReady was always false after a C# script was changed. Calling ReInput.Reset() didn't help, either. So I created a prefab of the Rewired Input Manager and instantiated a new one after a check to make sure Unity has finished recompiling.
Here's the code I placed in my own InputManager's Update() method, before all of my calls to player0.GetButton() and player0.GetAxis():
if (UnityEditor.EditorApplication.isCompiling) { return; } if (!ReInput.isReady) { Debug.LogWarning("ReInput isn't ready"); if (!reinitializing) { reinitializing = true; Instantiate(prefabReinputManager); } return; } reinitializing = false; var player0 = ReInput.players.GetPlayer(0); // make all of your calls to player0.GetButton(), etc., here
2. Reinitialize any static variables in your game - at least, the important ones
All static variables' values get reset after a recompile. That kinda sucks. But, depending on how your existing code is written, you should be able to work around it in most cases.This part will depend a bit on how your own code is set up.
For me, most of my static variables aren't terribly crucial. If they get reset, they get reset. They might result in a few weird symptoms during a hot deployment -- symptoms that will go away if I restart my game and which, of course, won't affect any gameplay in a real build where hot deployment is impossible-- but, for the most part, it's nothing major.
But there's one area that does get affected in a major way for me, and I suspect it'll be a major issue for most developers as well: singletons. For example, I have a Game.cs class that acts as a singleton class, containing a bunch of information about the current general state of the game. It has a static variable that points to itself, so other classes in my game can access it, like so:
static Game instance = null;
public void Start() { Game.instance = this; }This gets set back to null whenever a hot redeployment happens, and everything that needs access to the Game instance breaks.
But there's an easy fix. I just check, in Game.Update(), whether the reference has somehow reset back to null, like so:
public void Update() { if (Game.instance == null) { Game.instance = this; } }There are a couple of other ways to go about this part, but that works well and is quick and easy to explain.
That's about it. With all of this in mind, you should now be able to use hot deployment in Unity even when you're using Rewired.