Jump to content
Unity Insider Forum
Sign in to follow this  
Sanban

Neue Objekte im Editor Window über Button erstellen

Recommended Posts

Hallo. Ich bin noch recht neu im Thema Editor Window. Ich möchte über das drücken eines Buttons zwei neue Textfelder in meinem Editor Window "spawnen". Der Code sieht folgendermaßen aus:

void OnGUI()
    {
        if(GUILayout.Button("Add new Item"))
        {
            pressed = true;
            Debug.Log(pressed);
        }


        index = EditorGUILayout.Popup("Language", index, options);
    }

    void Update()
    {
        if (pressed == true)
        {
            GUILayout.BeginHorizontal();
            EditorGUILayout.TextField("Name");
            EditorGUILayout.TextField("Name");
            GUILayout.EndHorizontal();
            pressed = false;
            Debug.Log(pressed);
        }
    }

Nun bekomme ich beim drücken des Buttons folgenden Error:

Zitat

NullReferenceException: Object reference not set to an instance of an object
UnityEngine.GUILayoutUtility.BeginLayoutGroup (UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options, System.Type layoutType) (at C:/buildslave/unity/build/Modules/IMGUI/GUILayoutUtility.cs:298)
UnityEngine.GUILayout.BeginHorizontal (UnityEngine.GUIContent content, UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options) (at C:/buildslave/unity/build/Modules/IMGUI/GUILayout.cs:243)
UnityEngine.GUILayout.BeginHorizontal (UnityEngine.GUILayoutOption[] options) (at C:/buildslave/unity/build/Modules/IMGUI/GUILayout.cs:234)
ExampleWindow.Update () (at Assets/Scripts/ExampleWindow.cs:40)
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222)
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:232)
System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MethodBase.cs:115)
UnityEditor.HostView.Invoke (System.String methodName, System.Object obj) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:295)
UnityEditor.HostView.Invoke (System.String methodName) (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:288)
UnityEditor.HostView.SendUpdate () (at C:/buildslave/unity/build/Editor/Mono/HostView.cs:367)
UnityEditor.EditorApplication.Internal_CallUpdateFunctions () (at C:/buildslave/unity/build/Editor/Mono/EditorApplication.cs:191)
 

Gibt es hier vielleicht jemand der schonmal Erfahrung damit gemacht hat und mir weiter helfen könnte?

Share this post


Link to post
Share on other sites

IMGUI-Code gehört keinesfalls in Update. Woher deine Fehlermeldung jetzt genau kommt, kann ich nicht sagen, aber wenn du deinen UI-Code nur noch in OnGUI bzw. den ausschließlich darin aufgerufenen Methoden hast, läst sich das Problem vermutlich von alleine.

Share this post


Link to post
Share on other sites

Anfänglich war der Code auch in OnGUI. Doch wenn ich dort auf den Button gedrückt habe sind keine Textfelder erschienen. Die Logs haben aber das setzten des bools auf true und anschließend wieder auf false zurück gegeben.

Share this post


Link to post
Share on other sites

Musst halt deine bools außerhalb der Methode haben, damit sie bleiben.

private bool displayLabel;

private void OnGUI()
{
  if (GUILayout.Button("Toggle Label"))
  {
    displayLabel = !displayLabel;
  }
  
  if (displayLabel)
  {
    GUILayout.Label("Hi there.");
  }
}

 

Share this post


Link to post
Share on other sites

Danke erstmal für dein Beispiel. Dadurch konnte ich den Fehler finden. Nur möchte ich ja allerdings nicht das es immer auf true bleibt sondern das es nach dem das neue Objekt hinzugefügt wurde wieder auf false gesetzt wird. Ich möchte über den Button beliebig viele Objekte hinzufügen können. Ich sehe das das Problem das pressed = false; nach dem erstellen der Textfelder war. Nehm ich es raus erscheinen sie. Aber eben nur einmalig weil der bool ja danach nicht mehr auf false zurück gesetzt wird. Ich bin gerade etwas unsicher wo genau der bool dann wieder zurück gesetzt wird weil wenn ich ihn in der if am Ende lasse erscheinen die beiden Textfelder ja nicht.

Share this post


Link to post
Share on other sites

Sowas?

private bool displayPopup;
private int number = 0;

private void OnGUI()
{
  GUILayout.Label("number: " + number);
  
  if (GUILayout.Button("Show popup"))
  {
    displayPopup = true;
  }
  
  if (displayPopup)
  {
    if (GUILayout.Button("Count + 1"))
    {
      number++;
      displayPopup = false;
    }
  }
}

Du hast ja schon bestimmte Momente, in denen die Werte geändert werden sollen (in diesem Fall displayPopup). Du musst halt dafür sorgen, dass die Wertänderung ausschließlich dann passiert, wenn du sie auch haben willst, z.B. beim Klicken eines Knopfes.

Share this post


Link to post
Share on other sites

Danke für deine Antwort und sry für meine späte. Ich glaube wir reden etwas an einander vorbei. das Popup soll nie ausgeblendet werden. Um vielleicht mal etwas aus zu holen was ich allgemein machen möchte: ich arbeite atm an einem MultilanguageTool. Das Popup soll die wahl der Sprache sein und unterhalb des Popups sollen Textfelder für jedes UI-Textfeld erscheinen, welches einen bestimmten Komponenten hat. Ich bin jetzt dazu übergangen mit die Objekte mit FindObjectsOfType zu holen. Nur mein aktuelles Problem ist das die Textfelder sekündlich neu erstellen werden (auch wenn nur so viele zu sehen sind wie es IDs gibt). Dies haut mir allerdings die Länge meiner data-List in die Höhe. Ich habe nun testweise eine if eingebaut um zu verhindern das die Liste permanent verlängert wird

if(textFieldCount < texts.Length)
            {
                for (int i = 0; i < texts.Length; i++)
                {
                    GUILayout.BeginHorizontal();
                    GUILayout.Label(texts[i].ID);


                    Languages[index].data.Add("");
                    Languages[index].data[i] = GUILayout.TextField(Languages[index].data[i]);
                    textFieldCount++;

                    Debug.Log(Languages[index].data.Count);
                    GUILayout.EndHorizontal();
                }
            }

Im Bezug auf die Data-List funktioniert das super. Es gibt 2 Objekte und die Data-List ist nun auch 2 lang. Nur werden mir allerdings jetzt meine TextFields nichtmehr angezeigt. An sich war dies auch vor ca einer halben Woche mein Problem als ich die TextFields noch per Buttonpress hinzufügen wollten. Das diese halt nichtmehr angezeigt werden sobald ich den bool auf false gesetzt hatte. Ich bin mir nur gerade nicht sicher wie ich es beheben kann das A meinste Liste nicht wieder ins unendliche erweitert und und B mir dennoch meine TextFields angezeigt werden.

Share this post


Link to post
Share on other sites
vor 42 Minuten schrieb Sanban:

das Popup soll nie ausgeblendet werden.

Mein Code war 100% Beispielcode. Es gibg darum, zu zeigen, dass du Werte im IMGUI-Code an bestimmten stellen ändern musst, z.B. beim Drücken eines Knopfes.

Dein neuer Post und Code wirken so, als gäbe es ein grundsätzliches Verständnisproblem mit IMGUI. Zeilen wie "GUILayout.Label" erzeugen keine neuen UI-Elemente - sie zeigen sie einmalig an... vereinfacht ausgedrückt. Wenn du also in jedem OnGUI-Aufruf fünf Mal GUILayout.Label aufrufst, dann wirst du fünf Labels sehen.

Wenn du Daten in ein IMGUI-Interface speisen willst (also z.B. eine Liste anziegen), dann sollte diese Liste außerhalb des UI existieren, und das gleiche gilt, wenn du Daten über IMGUI erstellen willst.

Hier hast du Beispielcode für das Anzeigen und Bearbeiten einer Liste. Beachte, wie die Liste nur dann erweitert wird, wenn man auf "Hinzufügen" klickt. Der Inhalt der Liste ändert sich niemals zum Zweck der Anzeige im UI.

private List<string> list = new List<string>();

private OnGUI()
{
  var deleteIndex = -1;
  
  for (var i = 0; i < list.Count; i++)
  {
    GUILayout.BeginHorizontal();
    // Textfeld zum Bearbeiten
    list[i] = GUILayout.TextField(list[i]);
    // Knopf zum Löschen
    if (GUILayout.Button("X", GUILayout.Width(26)))
    {
      deleteIndex = i;
    }
    
    GUILayout.EndHorizontal();
  }
  
  if (deleteIndex > -1)
  {
    list.RemoveAt(deleteIndex);
  }
  // Knopf zum Hinzufügen
  else if(GUILayout.Button("Hinzufügen"))
  {
    list.Add("");
  }
}

 

Share this post


Link to post
Share on other sites

Danke, deine Antwort hat mir sehr weiter geholfen. Ich bin davon ausgegangen das wenn Elemente einmal erstellt wurden auch bleiben like Instantiate.

  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×