Handles.Button unresponsive in custom editor after custom asset serialization

I’m making a custom node editor in Unity to use as a base from which to make more specific editors for things like dialogue trees.

A key part of this editor is the ability to create connections between nodes, and also for the user to be able to modify these connections immediately, after they’re created.

To modify a connection, I’m using a Handle.Button with a circle cap that the user can click on, which calls a function that deletes the existing connection and starts a new one of the same connection type.

You can see what this looks like below. I’ve circled two Handle.Button 's in red for clarity:

These buttons work fine initially, but when the scene is saved and the custom assets that hold these connections are serialized and Unity then reloaded, these buttons become unresponsive. Only new connections are responsive, and even then, clicking one of the Handle buttons from these new connections deletes one of the unresponsive connections.

There’s too much code for me to chop out the relevant bits and paste them here, so here’s a link to the public GitHub repo that you should be able to pull the project from:

You can access the editor in Unity by going:

Window/Custom/NodeEditor.

The key scripts are the NodeConnection script, which is where the connections and Handle.Button circles are drawn:

Assets\NodeEditor\Scripts\NodeConnections

and the NodeEditor, which is the key Custom Editor script that handles most of what the editor does and looks like.

There’s a bit to look through, but I would massively appreciate any help because this has stumped me.

Thanks in advance,
Matt

It appears that Handle controls (Handles.Button(), Handles.PositionHandle(), etc) do not work outside of OnSceneGUI(), as it throws a Null Reference Exception. You need to use GUI.Button() instead. Just edit your code like so:

		//HERE IS THE HANDLE BUTTON
		Vector2 pos = midPoint - new Vector2(10f, -4f);
		Vector2 size = new Vector2(8f, 8f);
		Rect rect = new Rect(pos-size, size*2);
		if (GUI.Button(rect, GUIContent.none, GUIStyle.none))
		{
			Debug.Log(outputNode.nodeName);
			NodeEditor.ReAssignConnection(connectionType, outputNode);
			outputNode.nodeConnections.Remove(this);
		}

You may want to laugh out loud. I tracked down the problem to the zoom slider control ^^. For some reason it doesn’t work with the normal layout system. The problem is that the slider control draws it’s content conditionally based on the available width. However, as you might know, during the layout event all rect allocation methods for the layout system return the rect “(0,0,1,1)” since the layouting hasn’t been finished yet. Though this makes the slider use the minimal control version. At all other events however it now has more “space” available and draws the “extended” version. This results in many additional controlID allocations which messes up all control ids which are allocated after this slider ^^.

Comment that one line out and it will work again ^^. It should also work when you make your window smaller in width so the slider is hidden and only the input field stays.

That was one weird error ^^. It’s really strange since the slider is also used in the terrain inspector, but since the built-in inspectors use an optimised GUI block that problem most likely doesn’t show up.

So it is a bug in the EditorGUILayout.Slider implementation. To fix this Unity has to completely rewrite it. Though that auto mode-change thing can’t really be implemented with normal the layout system… Maybe they remove it completely ^^.

I suggest you simply rebuild the same with a normal slider and a float field.