Recreate default editor look manually without base.OnInspectorGUI [UnityEditor]

I am trying to create my own custom editor. But I wanted to start with recreating the default editor look without using the base.OnInspectorGUI method.

I managed it somewhat, with 2 main issues.

1) I cannot recreate the greyed out “Script” horizontal line + it points to the target object rather than open the script in editor when clicked

2) My toggles do not work. I can click on them but they don’t toggle on and off.

124826-combined.png

Here is the snippet of my new custom editor

using UnityEditor;

[CustomEditor(typeof(LineScript))]
public class LineScriptCustomEditor : Editor
{
 public override void OnInspectorGUI()
    {
        LineScript myTarget = (LineScript)target;

        //base.OnInspectorGUI();

        LineScript lineScript_Editor = myTarget.GetComponent<LineScript>();
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.PrefixLabel("Script");
        lineScript_Editor = (LineScript)EditorGUILayout.ObjectField(lineScript_Editor,typeof(LineScript),false);
        EditorGUILayout.EndHorizontal();

        GameObject triggerOfInfoPanel_Editor = myTarget.GetComponent<LineScript>().triggerOfInfoPanel;
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.PrefixLabel("Trigger Of InfoPanel");
        triggerOfInfoPanel_Editor 
            = (GameObject)EditorGUILayout.ObjectField(triggerOfInfoPanel_Editor, typeof(GameObject),true);
        EditorGUILayout.EndHorizontal();

        GameObject popupScriptHolder_Editor = myTarget.GetComponent<LineScript>().PopupScriptHolder;
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.PrefixLabel("Popup Script Holder");
        myTarget.GetComponent<LineScript>().PopupScriptHolder
            = (GameObject)EditorGUILayout.ObjectField(popupScriptHolder_Editor, typeof(GameObject), true);
        EditorGUILayout.EndHorizontal();

        myTarget.GetComponent<LineScript>().widthFirst = EditorGUILayout.Toggle("Width First", false);
        myTarget.GetComponent<LineScript>().DebugDirections = EditorGUILayout.Toggle("Debug Directions", false);
        myTarget.GetComponent<LineScript>().DebugLinePositions = EditorGUILayout.Toggle("Debug Line Positions", false);
        myTarget.GetComponent<LineScript>().DebugEdgePoints = EditorGUILayout.Toggle("Debug Edge Points", false);

Here are the relevant parts in the Line Script

public class LineScript : MonoBehaviour
{
    public GameObject triggerOfInfoPanel;
    public GameObject PopupScriptHolder;
    public bool widthFirst;
    public bool DebugDirections;
    public bool DebugLinePositions;
    public bool DebugEdgePoints;

 ....

Any idea how to fix 2 issues I have ?

Actually you have several issues in your script. First of all all those GetComponent calls are unnecessary and actually create more errors than they might solve. “myTarget” is already a reference to the LineScript that this editor is editing. Using GetComponent might actually return the wrong script in case there are several scripts on the same gameobject. As i said the GetComponent call is completely unnecessary anyways.

Next is your editor only supports single object editing. The “target” variable was the old way how custom inspectors were written. Usually you would use the SerializedObject / SerializedProperty instance(s) that the editor is providing. The SerializedProperty class represents an iterator through all serializable values of an object including sub classes. Though if you really want to manually implement every field yourself, go ahead.

About your concrete issues. First of all the script field does not reference the script instance but the MonoScript instance that implements the class. You can use MonoScript.FromMonoBehaviour to get the reference to the MonoScript asset which implements the given MonoBehaviour.

You can make any GUI control “disabled” (grayed out) by setting GUI.enabled to false before you draw it. Keep in mind to set it back to true after drawing it since this is a state that affects all controls. In some cases it might be convenient to use EditorGUI.BeginDisabledGroup / EndDisabledGroup to disable certain controls and automatically restore the enabled state in EndDisabledGroup.

Your toggles don’t work because you don’t pass in the current boolean state. You always pass in false and assign the result to the variable. You have to do

myTarget.widthFirst = EditorGUILayout.Toggle("Width First", myTarget.widthFirst);

Finally your editor does not use any Undo registration which also means that the changes your editor may apply to your edited object might not be saved. You might want to have a look at the Undo class and the RecordObject method.

What’s exactly the reason you want to implement the whole GUI manually? You may want to have a look at the Editor documentation and the examples.

Thank you for the answer. I found it hard to find information on this, so this is very useful. I was trying things almost blindly, following some tutorials.

Part of the reason I wanted to recreate it manually was to add space between the “Width First” and other toggles, which I think you can’t do if you use base.OnInspectorGUI (I might be wrong about this), the other part was just figuring how this works and with your help I am definitely much closer to that.

I also added extra functionality. When you click the Debug options, the information appears in the editor. I just didn’t mention that part cause I solved it.

I’ll try work around what you mentioned.

I just wanted to thank the previous poster for his post. It helped immensely.

I have not applied all the things he mentioned yet. Particularly using Serialize and applying the Undo class / RecordObject method.

However. I applied the previous 3 things he mentioned.

1) Using theMonsoScript instance to get the asset rather than the script instance

2) Using GUI.enabled to gray a field out

3) Making my toggles work

I will post what I did so it helps others in the future.

1) this

MonoScript lineScriptAsset = MonoScript.FromMonoBehaviour(myTarget);
lineScriptAsset = (MonoScript)EditorGUILayout.ObjectField(lineScriptAsset, typeof(MonoScript), true);

instead of this

myTarget = (LineScript)EditorGUILayout.ObjectField(myTarget, typeof(LineScript), true);

2) added these 2 lines

MonoScript lineScriptAsset = MonoScript.FromMonoBehaviour(myTarget);
        GUI.enabled = false;  //   <---------------------------- this part here
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.PrefixLabel("Script");
        lineScriptAsset = (MonoScript)EditorGUILayout.ObjectField(lineScriptAsset, typeof(MonoScript), true);
        EditorGUILayout.EndHorizontal();
        GUI.enabled = true; // <------------------------------- and this part here

3) this

myTarget.GetComponent<LineScript>().widthFirst 
= EditorGUILayout.Toggle("Width First", myTarget.widthFirst);

myTarget.GetComponent<LineScript>().DebugDirections 
= EditorGUILayout.Toggle("Debug Directions", myTarget.DebugDirections);

myTarget.GetComponent<LineScript>().DebugLinePositions 
= EditorGUILayout.Toggle("Debug Line Positions", myTarget.DebugLinePositions);

myTarget.GetComponent<LineScript>().DebugEdgePoints 
= EditorGUILayout.Toggle("Debug Edge Points", myTarget.DebugEdgePoints);

instead of this

myTarget.GetComponent<LineScript>().widthFirst 
= EditorGUILayout.Toggle("Width First", false);

myTarget.GetComponent<LineScript>().DebugDirections 
= EditorGUILayout.Toggle("Debug Directions", false);

myTarget.GetComponent<LineScript>().DebugLinePositions 
= EditorGUILayout.Toggle("Debug Line Positions", false);

myTarget.GetComponent<LineScript>().DebugEdgePoints 
= EditorGUILayout.Toggle("Debug Edge Points", false);

And now my editor looks like this and works like the original
124886-neweditorlook.png

Which is almost like the original, except the toggles are not perfectly aligned with the object fields
124887-originaleditorlook.png

But it works just like the original (although I am not sure about the RecordObject method as the previous user mentioned, I’ll need to look into that).

So thanks to the original poster. It is exactly what I needed.
The only question left for now being how to align the toggles and the object field and then it will be perfect.