Hdg Remote Debug works using .NET’s reflection features; it doesn’t use any sort of built-in Unity serialisation. Every second it gathers all GameObjects
that are currently active, finds all Components
on them, and for each component, uses reflection to find all serialised and public fields. This data is sent back to the client running in the editor over a network connection, where the data is displayed in custom hierarchy and inspector windows.
This means it doesn’t use the built-in Unity inspectors or any custom inspectors you may have created, so when you click on, say, a Camera
object you see the public and serialised fields of the Camera
type rather than what Unity’s built-in CameraEditor
inspector would have shown.
I would like to fix this and use the built-in inspectors and I have actually prototyped it extensively but it turns out there are several problems. To use the built-in inspectors we require a proxy GameObject
that represents the selected object on the server. The idea is that whenever we receive a message from the server, we create a new proxy GameObject
, dynamically add all components to it, and for each component, create an Editor
instance with Editor.CreateEditor(component)
. When drawing the UI for the components, we just call Editor.OnInspectorGUI
for each one and use BeginChangeCheck/EndChangeCheck
to determine if anything changed. If fields have changed we send a message to the server to update it.
There are a couple of problems with this approach. The built-in inspectors cause undo events to be added to the system, but those undo events are undesirable; the GameObject
is a temporary proxy object for which we don’t want to track undo events. In fact the object is not visible in the scene, so the undo events seem spurious to the user. It’s not a good user experience to generate all these undo events that go nowhere.
Another problem is that EndChangeCheck
doesn’t detect that changes have happened when certain fields are changed. One such field that I found was the camera mask property. It seems to be something to do with the EditorGUI.PropertyField
, which doesn’t seem to set GUI.changed
to true.
The last major problem is with the proxy GameObject
. We create a new proxy every time we receive a message from the server, but destroying the previous one seems to cause the Editor
objects that we created to throw NullReferenceExceptions
when you hit play or when Unity reloads assemblies, when it tries to reinitialise its serializedObject
field. I think I need to find a way to clear the reference on the Editor
when destroying the GameObject
, but it wasn’t possible when I last investigated. I can’t just leave the proxy object; that’s a memory leak!
I have a Trello roadmap board with some features I’d like to add. Some are wishlist features which may not really be possible without digging into the Unity source (e.g. hotswapping prefabs, or the aforementioned built-in inspectors). One feature I would like to add is an extensible console system, where you can hook in your own commands to control the game remotely. That way you can add debug features to the game that you can then control from Unity.
Get in touch if you have any questions or feature requests for Hdg Remote Debug!