Custom editor window not opening.

I have been programming a custom editor window to show tree diagrams of dialogue paths. It was all working fine, but now the window has stopped so much as opening, giving the following error the first time I attempt to create the window in Unity (but none of the other times after that from what I can tell):

“ArgumentException: You can only call GUI functions from inside OnGUI.
UnityEngine.GUIUtility.CheckOnGUI () (at C:/buildslave/unity/build/Runtime/IMGUI/Managed/GUIUtility.cs:208)
UnityEngine.GUI.get_skin () (at C:/buildslave/unity/build/Runtime/IMGUI/Managed/GUI.cs:55)
DialogueGUI…ctor ()
UnityEditor.EditorWindow:GetWindow(Type)
DialogueGUI:ShowWindow() (at Assets/Editor/Dialogue Backend/DialogueGUI.cs:20)”

I try double clicking the error message, and it takes me to the line containing the GetWindow function, but this has always worked previously, so I don’t understand what is wrong - has something in Unity changed? I can’t remember if I updated between the last time it worked and now, and I can’t find or think of anything new that is a GUI function running outside of OnGUI. If someone could help me understand what is wrong it would be much appreciated!

The entirety of the script controlling the window is as follows (I included all of it just in case, as I have no idea what the problem is):

using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

[System.Serializable]
public class DialogueTreeBox
{
    public Rect mainRect {get;set;}
}

public class DialogueGUI : EditorWindow {

    [MenuItem("Window/DialogueGUI")]

    public static void ShowWindow()
    {
        GetWindow(typeof(DialogueGUI));
        Debug.Log("Window Loaded.");
    }

    public GUIStyle titleStyle;

    //Tree Variables
    public Texture backgroundTexture; //The texture of the background of the tree-editing area
    public Rect windowRect = new Rect(200, 100, 160, 160);
    public Rect windowRect2 = new Rect(100, 100, 160, 160);
    public Vector2 nodeSize = new Vector2(160, 160); //The x and y sizes of the node windows
    public string[] nodeTypeOptions = new string[] {"Monologue","Dialogue","Script"}; //The different possible types of node
    public List<DialogueNode> nodes = new List<DialogueNode>();
    public GUIStyle smallFontButton = new GUIStyle(GUI.skin.button);
    private int scrollSizeY = 10000; //The max vertical size of the tree-editing area
    private int scrollSizeX = 10000; //The max horizontal size of the tree-editing area
    private Vector2 scrollPos = Vector2.zero;

    //Character Dropdown Box
    public string[] options = new string[3];
    public int index = 0;

    //Run when unity is started up?
    public void OnEnable()
    {
        backgroundTexture = (Texture)Resources.Load("DGBT",typeof(Texture));
    }

    void OnGUI() {


        if (smallFontButton.fontSize != 10)
        {
            smallFontButton = GUI.skin.button;
            smallFontButton.fontSize = 10;
        }

        GUI.DrawTextureWithTexCoords(new Rect(-5, 50, position.width + 10, position.height - 40), backgroundTexture, new Rect(0, 0, (position.width + 10)/400, (position.height - 40)/400));

        //Dropdown Box
        index = EditorGUI.Popup(
            new Rect(0, 10, 300, 20),
            "Character:",
            index,
            options);

        //Add Character
        if (GUI.Button(new Rect(400, 10, 200, 26), "Add Character"))
            AddCharacterToObjects();

        //Save Tree
        if (GUI.Button(new Rect(630, 10, 200, 26), "Save Tree"))
        {
            //Do saving stuff
        }

        //Add Node
        if (GUI.Button(new Rect(860, 10, 200, 26),"New Node"))
        {
            int i = FirstEmptyIndex(nodes);
            nodes.Insert(i,new DialogueNode());
            nodes[i - 1].nodeRect = new Rect(100,100,160,160);
            nodes[i - 1].nodeID = i - 1;
        }

        //Show Number Of Nodes
        GUI.Box(new Rect(1090, 13, 100, 20), "Nodes: " + nodes.Count);

        scrollPos = GUI.BeginScrollView(new Rect(0, 50, position.width, position.height - 50), scrollPos, new Rect(0, 0, scrollSizeX, scrollSizeY));

        Handles.BeginGUI();

        if (nodes.Count > 0)
        {
            for (int i = 0; i < nodes.Count; i++)
            {
                for (int j = 0; j < nodes[i].proceedingNodes.Count; j++)
                {
                    Handles.DrawAAPolyLine(4, new Vector3[] {
                        new Vector3 (
                        nodes[i].nodeRect.center.x,
                        nodes[i].nodeRect.center.y,
                        0),
                        new Vector3(
                        nodes[nodes[i].proceedingNodes[j]].nodeRect.center.x,
                        nodes[nodes[i].proceedingNodes[j]].nodeRect.center.y,
                        0) });
                }
            }
        }

        Handles.EndGUI();

        BeginWindows();
        for(int i = 0; i < nodes.Count; i++)
        {
            nodes[i].nodeRect = GUI.Window(i, nodes[i].nodeRect, WindowFunction, nodes[i].nodeTypeString);
        }

        EndWindows();

        for(int i = 0; i<nodes.Count; i++)
        {
            if (nodes[i].nodeRect.x < 0)
                nodes[i].nodeRect.x = 0;
            else if (nodes[i].nodeRect.x > scrollSizeX)
                nodes[i].nodeRect.x = scrollSizeX - 160;
            if (nodes[i].nodeRect.y < 0)
                nodes[i].nodeRect.y = 0;
            else if (nodes[i].nodeRect.y > scrollSizeY)
                nodes[i].nodeRect.y = scrollSizeY - 160;
        }

        GUI.EndScrollView();

    }

    void WindowFunction (int windowID) {

        nodes[windowID].nodeType = EditorGUI.Popup(
            new Rect(5, 20, 150, 20),
            nodes[windowID].nodeType,
            nodeTypeOptions
        );
        switch (nodes[windowID].nodeType)
        {
            case 0:
                nodes[windowID].nodeTypeString = "Monologue";
                break;

            case 1:
                nodes[windowID].nodeTypeString = "Dialogue";
                break;

            case 2:
                nodes[windowID].nodeTypeString = "Script";
                break;

        }
        //Layout for node if it's a monologue node
        if (nodes[windowID].nodeType == 0)
        {
            GUI.TextArea(new Rect(5, 45, 150, 105),"");
        }
        //Layout for node if it's a dialogue node
        else if (nodes[windowID].nodeType == 1)
        {
            GUI.TextArea(new Rect(5, 45, 150, 90), "");
        }
        //Layout for node if it's a script node
        else if (nodes[windowID].nodeType == 2)
        {
            //Stuff for callbacks
        }

        //Show Node ID
        GUI.Box(new Rect(0, 0, 20, 15), "" + nodes[windowID].nodeID, smallFontButton);

        //Connect To Another Node
        if (GUI.Button(new Rect(20, 0, 20, 15), "/", smallFontButton))
        {
            //Show box to choose node to connect etc.
        }

        //Add New Node Proceeding This Node
        if (GUI.Button(new Rect(120,0,20,15),"+", smallFontButton))
        {
            int i = FirstEmptyIndex(nodes);
            nodes.Insert(i, new DialogueNode());
            nodes[i - 1].nodeID = i - 1;
            nodes[i - 1].nodeRect = new Rect(nodes[windowID].nodeRect.x, nodes[windowID].nodeRect.y + 200, 160, 160);
            nodes[i - 1].preceedingNodes.Insert(nodes[i - 1].preceedingNodes.Count, windowID);
            nodes[windowID].proceedingNodes.Insert(nodes[windowID].proceedingNodes.Count, i - 1);
        }
       
        //Remove Current Node
        if (GUI.Button(new Rect(140,0,20,15),"x", smallFontButton))
        {
            for (int i = 0;i < nodes[windowID].preceedingNodes.Count; i++)
            {
                nodes[nodes[windowID].preceedingNodes[i]].proceedingNodes.Remove(nodes[windowID].nodeID);
            }
            //The Rest Of The Stuff To Remove Node
        }

        GUI.DragWindow(); //Must be at the end

    }

    void AddCharacterToObjects() {

        if(!Selection.activeGameObject){
            Debug.LogError("Please select at least one GameObject first");
            return;
        }

        foreach(GameObject go in Selection.gameObjects) {
            switch (index) {
                case 0:
                    //do stuff
                    break;

                case 1:
                    //more stuff
                    break;

                case 2:
                    //continue this
                    break;

               
            }
        }
    }

    public int FirstEmptyIndex<T> (List<T> list)
    {
        int ret = 0;
        for(int i = 0; i < list.Count; i++)
        {
            if (list[i].Equals(default(T)))
            {
                ret = i;
                break;
            }
        }

        if (ret == 0)
            ret = list.Count;
        return ret;
    }
}

Thanks in advance for the help!

Try this:

DialogueGUI window = EditorWindow.GetWindow<DialogueGUI>();
window.Show();

Thanks, but the problem still persists, although it’s possibly worth noting that the bottom two lines of the error message don’t show this time, and the error shows straight away after having changed and saved the code.

The bold line is a big hint to what’s going on… Your code is breaking due to the class’ constructor trying to do something.

Since you have no explicit constructor (which is good, Unity doesn’t like that for it’s built-in classes), it’s the implicit parameterless constructor that’s breaking. That exists in all classes, and sets your fields to have the default value. So the error is caused by one of your fields.

The error complaining about GUI.get_skin should make things easier, as there’s only one field that matches that:

public GUIStyle smallFontButton = new GUIStyle(GUI.skin.button);

That’s trying to construct a GUI style outside an OnGUI function. It’s easy to fix - make the call be lazy instead:

public GUIStyle smallFontButton;
....

void OnGUI() {
    if(smallFontButton == null)
        smallFontButton = new GUIStyle(GUI.skin.button);
}

Or just don’t have it as a field.

Ah ok, thank you, it works great now! Although it’s interesting, as it did previously work fine how it was.
Thanks a lot for the help!