How do I have my editor draw in the scene view?

I’ve got a very basic editor used for designing levels in my game. It has you pick 2 game objects and then creates a link between them. I want to visualize this so you can see the links that have been created. I was trying to accomplish this through some variant of DrawLine, either via Debug or Handles or Gizmos. So in the OnGUI method of my EditorWindow subclass I check for various things and then do my call to one of the DrawLine methods. Nothing shows up in the scene view until it receives focus. Is the scene view’s camera not be rendered since the scene view doesn’t have focus?

Editor functionality only works in the editor.

If you want an editor thats deliveried with the game you must write your own editor functioanlity.

I don’t want to deliver this editor with the game, I just want to be able to visualize the settings being made in the editor window, so you can click a link in the editor and see it visually on the screen.

Well, after quite a bit of testing and experimentation I settled in on a solution I can live with. I switched the editor over from an EditorWindow to a Custom Editor targeting the script that holds my level data. That way when you click on the “Level” prefab in the scene you get the editor in the inspector. This prefab is totally blank except for my script and I drop it into each level to control the loading of the level data my editor produces.

My final solution to make the scene view update nicely was simply to add this to my OnInspectorGUI method:

target.gameObject.transform.position.x += 0.1;
target.gameObject.transform.position.x -= 0.1;

Then I do all of my overlay drawing in the OnSceneGUI method which gets called because something in the scene moved. This means that anytime you change an option in the editor you immediately see the results but you’re not spamming a redraw of the scene as the OnInspectorGUI events happen only when you’re active in the editor. I felt this was a pretty nice compromise as far as dirty hacks go. Here is the full code, most of the editor stuff is totally useless for any other project but hopefully there’s some useful code in there for others with a similar problem.

@CustomEditor(LevelData)
class LevelEditorComponent extends Editor {
	private static var startPickedObject : GameObject;
	private static var endPickedObject : GameObject;
	private static var selectedEdge : int = 0;
	private static var selectedShape : int = 0;
	
	function OnInspectorGUI() {
		GUILayout.Label("Create link", "BoldLabel");

		startPickedObject = EditorGUILayout.ObjectField("Start dot", startPickedObject, GameObject);
		endPickedObject = EditorGUILayout.ObjectField("End dot", endPickedObject, GameObject);
		var edgeLabels = new Array();
		var shapeLabels = new Array();

		if(GUILayout.Button("Create New Edge", GUILayout.Width(150))) {
			if(startPickedObject != null  endPickedObject != null) {
				target.AddEdge(new Edge(startPickedObject, endPickedObject));
				startPickedObject = null;
				endPickedObject = null;
			}
		}
		
		for(var i = 0; i < target.GetEdges().length; i++) {
			edgeLabels.Add("Edge " + i);
		}
		selectedEdge = GUILayout.SelectionGrid(selectedEdge, edgeLabels.ToBuiltin(String), 1);
		
		if(GUILayout.Button("Create New Shape", GUILayout.Width(150))) {
			target.AddShape(new Shape());
		}
		
		for(i = 0; i < target.GetShapes().length; i++) {
			shapeLabels.Add("Shape " + i);
		}
		selectedShape = GUILayout.SelectionGrid(selectedShape, shapeLabels.ToBuiltin(String), 1);

		ForceSceneRedraw();
	}
	
	function OnSceneGUI() {
		if(startPickedObject) {
			Handles.Label(startPickedObject.transform.position, "Start");
		}

		if(endPickedObject) {
			Handles.Label(endPickedObject.transform.position, "End");
		}
		
		for(var dot : GameObject in GetAllDots()) {
			Handles.Label(dot.transform.position + Vector3(0, 200, 0), dot.name);
		}
		
		var edges = target.GetEdges();
		for(var i = 0; i < edges.length; i++) {
			if(selectedEdge == i) {
				Handles.color = Color.white;
			}
			else {
				Handles.color = edges[i].GetGizmoColor();
			}

			Handles.DrawLine(edges[i].GetStart().transform.position, edges[i].GetEnd().transform.position);
			Handles.Label(Vector3.Lerp(edges[i].GetStart().transform.position, edges[i].GetEnd().transform.position, 0.35), "Edge " + i);
		}
	}
	
	private function ForceSceneRedraw() {
		target.gameObject.transform.position.x += 0.1;
		target.gameObject.transform.position.x -= 0.1;
	}
	
	private function GetAllDots() {
		return GameObject.FindGameObjectsWithTag("Dot");
	}
}

Many, many thanks for sharing this hack. It works like a charm for any script that needs interactive updates in editor mode :smile:.

A bit old thread, but if anyone finds it on google.

The simplest way to get a redrew is to call EditorUtility.SetDirty(GameObject) on the gameobject you wish to redraw. In this way you don’t have to manipulate random variables…

Thanks for that.