Jump to content
Unity Insider Forum

GameObjects togglen (ein- und ausblenden)


DanielG

Recommended Posts

Hallo,

ich versuche gerade mithilfe eines Mausklicks alle Buttons ein- bzw. auszublenden.
Mein aktuelles Skript ist das hier:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
	public class PanelToggle : MonoBehaviour
{
    private bool buttonStatus = true; // Mit wahr initialisieren
    public void ToggleButtons() // Alle Buttons ein- bzw. ausblenden
    {
      buttonStatus = !buttonStatus; // buttonStatus togglen
      GameObject[] buttonArray = GameObject.FindGameObjectsWithTag("Button"); // Array aus allen GameObjects generieren, die Buttons sind
      
      foreach (GameObject button in buttonArray) // Für alle Buttons:
      {
        button.SetActive(buttonStatus); // Aktuellen Button ein- bzw. ausblenden
        Debug.Log("Buttons sind: " + buttonStatus); // OK
      }
    }
}

Dieses habe ich an die Main Camera gehangen.
Meinem Panel habe ich die "Button Componente" gegeben und in der OnClick Funktion (im Inspector)
hab ich dann die Main Camera reingezogen und die FUnktion ausgewählt.
(K.a. ob es einfacher geht.)

Starte ich den Playmode, werden die Buttons ausgeblendet, sobald ich auf das Panel klicke (alles richtig).
Klicke ich erneut, werden sie aber nicht eingeblendet.

Wo liegt der Fehler?

Danke für jede Hilfe!

Link zu diesem Kommentar
Auf anderen Seiten teilen

Moin,

Du suchst die Buttons, wenn Du ToggleButtons() aufrufst. Das Problem hierbei ist, dass Unity keine GameObjects in der Scene findet, die inaktiv sind. Die einfachste und sauberste Lösung ohne zu viel zu ändern wäre die folgende Änderung, einmal beim Start die Buttons zu finden und dann nur noch das Array zu nutzen.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
	public class PanelToggle : MonoBehaviour
{
    private bool buttonStatus = true; // Mit wahr initialisieren
      private GameObject[] buttonArray;
      
      void Start()
      {
        //Buttons beim Start einmal suchen und im Array cachen.
        buttonArray = GameObject.FindGameObjectsWithTag("Button"); // Array aus allen GameObjects generieren, die Buttons sind
      }
      
    public void ToggleButtons() // Alle Buttons ein- bzw. ausblenden
    {
      buttonStatus = !buttonStatus; // buttonStatus togglen
      
      foreach (GameObject button in buttonArray) // Für alle Buttons:
      {
        button.SetActive(buttonStatus); // Aktuellen Button ein- bzw. ausblenden
        Debug.Log("Buttons sind: " + buttonStatus); // OK
      }
    }
}

Grundsätzlich würde ich aber von "FindGameObjectsWithTag" und anderen Suchfunktionen mit String-Namen abraten, weil das sehr fehleranfällig ist.

Entweder direkt nach Components suchen, oder ein im Inspector zugängliches Feld machen, wo Du die Buttons einfach im Editor reinziehst.

//Hierfür müsste die Komponente auf dem Panel liegen und dann alle Unterelemente durchsuchen
GetComponentsInChildren<Button>()

//oder so, mit dem SerializeField Attribut erlaubst Du Unity, ein privates Feld im Inspector sichtbar zu machen
[SerializeField]
private Button[] buttonArray;
Link zu diesem Kommentar
Auf anderen Seiten teilen

Vielen Dank für deine Antwort, das funktioniert schon mal!

Ich habe noch ein wenig nachgedacht und bin zum Entschluss gekommen, dass es evt. sinnvoller wäre,
die Buttons transparent zu machen.
Dadurch müssen sie anfangs nicht gecacht werden, da nie die Gefahr bestehen wird, dass sie deaktiviert sind.

Außerdem wird es optisch auch einen besseren Eindruck machen, wenn diese aus- bzw. eingeblendet werden.
Leider verzweifle ich mal wieder an den Basics.
Das hier funktioniert schon mal nicht:

  public void ToggleButtons() // Alle Buttons ein- bzw. ausblenden
  {
    buttonStatus = !buttonStatus; // buttonStatus togglen
    foreach (GameObject button in buttonArray) // Für alle Buttons:
    {  
      //button.SetActive(buttonStatus); // Aktuellen Button ein- bzw. ausblenden
      button.GetComponent<Renderer>().SetTransparency(1f); // WIE MÜSSTE ES KORREKT SEIN?
      Debug.Log("Buttons sind: " + buttonStatus); // OK
    }
  }

Ich habe verschiedenes probiert, aber leider hat's nie geklappt.

P.S. Dein anderer Gedanke mit dem Inspector ist interessant, aber noch bin ich nicht so weit :)

Gruß

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo nochmal,

ich habe das Problem bereits selber gelöst: Die Buttons können jetzt transparent dargestellt werden,
statt komplett deaktiviert zu werden. :)
Es lag eingentlich nur daran, dass ich im Programmkopf die "using UnityEngine.UI;" vergaß.

Leider schaffe ich es nicht, die Button-Transparenz mithilfe einer for-Schleife von 255 auf 0 zu bekommen.
Anders gesagt: Es funktioniert zwar, aber es wirkt wieder wie An und Aus.

Meine eingebaute Verzögerung, die zwischen jedem Durchlauf ausgeführt werden soll, scheint nicht zu funktionieren.
Das ist der aktuelle Programmcode, der zwar funktioniert, aber genau wie der erste läuft:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; // Notwendig, damit z.B. auf die Image-Componente zugegriffen werden kann
	public class PanelToggle : MonoBehaviour
{
  private bool buttonStatus = true; // Mit wahr initialisieren
  private GameObject[] buttonArray; // Array aller Buttons
	  void Start() // Buttons beim Start einmal suchen und im Array cachen.
  {
    buttonArray = GameObject.FindGameObjectsWithTag("Button");   // Array aus allen GameObjects generieren, die Buttons sind
  }
	  public void ToggleButtons() // Alle Buttons ein- bzw. ausblenden
  {
    buttonStatus = !buttonStatus; // buttonStatus togglen
	    foreach (GameObject button in buttonArray) // Für alle Buttons:
    {
      Transparenz(buttonStatus, button); // Transparenz für aktuellen Button verändern   
      Debug.Log("Buttons sind: " + buttonStatus); // OK
    }
  }
	  public void Transparenz(bool buttonStatus, GameObject button) // Übergebenen Button entweder ein- oder ausblenden
  {
    byte alpha = 255; ; // Alphawert mit 255 initialisieren (keine Transparenz zu Beginn)
	    if (buttonStatus) // Wenn Button eingeblendet werden soll:
    {
      button.GetComponent<Image>().color = new Color32(255, 255, 255, 255); // Voller Alphawert (keine Transparenz)
    }
    else // Ansonsten, ausblenden:
    {
      for (int x = 0; x < 255; x++) // 255 Durchgänge
      {
        alpha--; // Alphawert in jedem Durchgang dekrementieren
        button.GetComponent<Image>().color = new Color32(255, 255, 255, alpha); // Neuer Alphawert für den Button
        StartCoroutine(Verzögerung()); // Verzögerungsfunktion ausführen  - FUNKTIONIERT LEIDER NICHT WIE GEWÜNSCHT!
      }
    }      
  }
  IEnumerator Verzögerung() // Fügt eine Verzögerung von 1000 Millisekunden hinzu
  {
    yield return new WaitForSeconds(1); // 1 Sekunde Verzögerung
  }
}
Link zu diesem Kommentar
Auf anderen Seiten teilen

Als Erstes würde ich dir empfehlen solche Sachen einfach zu animieren. Dafür musst du natürlich erst einmal lernen, wie das mit Animationen so funktioniert. Aber glaub mir, es lohnt sich.

Zu deinem Problem will ich aber auch noch was schreiben.

Du fährst eine Schleife durch, bei der du den Alphawert einfach solange erhöhst, bis er 255 erreicht hat. So eine Schleife wird komplett ausgeführt und erst danach geht es im Code weiter.
Da ist es komplett egal, ob du innerhalb der Schleife eine Coroutine startest. Das Einzige, was es bewirkt: Diese Coroutine wird 256 mal in diesem einen Frame gestartet. Sie würde dir dann auch nach der Sekunde Verzögerung 256 mal etwas ausgeben, wenn du hinter dem Yield etwas hättest, was ausgegeben würde. Da ist aber nichts!
Das was du da machst, passiert innerhalb eines Frames. Aus diesem Grund wirkt es so, als würde der Button sofort den neuen Zustand annehmen.
 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi und Danke für deinen Tipp.

Ja, den Animator kenne ich und damit habe ich auch schon gearbeitet.
Jetzt, wo du es sagst, scheint dieser Weg wohl doch der sinnvollere zu sein.

Obwohl ich mit dem Animator schon einige Sachen realisiert habe, hänge ich leider gerade fest.

Die Animation habe ich erstellt und dem Button (Image) hinzugefügt und diese auch in den Inspector reingezogen (bei Controller).
An der Main Camera hängt das Script und auch dort existiert eine Animator-Komponente (mit zugewiesenem Controller).
Der Animation (Fade-Out) habe ich die Variable Animation mit Integer 1 zugewiesen.
Sobald im Code diese auf 1 gesetzt wird, müsste also die Ausblend-Animation laufen.

Der Code ist dieser hier (im Vergleich zum anderen deutlich abgespeckter):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; // Notwendig, damit z.B. auf die Image-Componente zugegriffen werden kann
	public class PanelToggle : MonoBehaviour
{
  private bool buttonStatus = true; // Mit wahr initialisieren
  private GameObject[] buttonArray; // Array aller Buttons
  public Animator animator; // Variable für den Zugriff auf die Animator-Komponente
	  void Start() // Buttons beim Start einmal suchen und im Array cachen.
  {
    buttonArray = GameObject.FindGameObjectsWithTag("Button");   // Array aus allen GameObjects generieren, die Buttons sind
  }
	  public void ToggleButtons() // Alle Buttons ein- bzw. ausblenden
  {
    buttonStatus = !buttonStatus; // buttonStatus togglen
	    foreach (GameObject button in buttonArray) // Für alle Buttons:
    {
      Transparenz(buttonStatus, button); // Transparenz für aktuellen Button verändern   
      Debug.Log("Buttons sind: " + buttonStatus); // OK
    }
  }
  public void Transparenz(bool buttonStatus, GameObject button) // Übergebenen Button entweder ein- oder ausblenden
  {
    animator = GetComponent<Animator>(); // Zugriff auf die Animator-Komponente
    if (buttonStatus) // Wenn Button eingeblendet werden soll:
    {
      animator.SetInteger("Animation", 0); // Idle-Animation abspielen bzw. keine
    }
    else // Ansonsten, ausblenden:
    {
      animator.SetInteger("Animation", 1); // Fade-Out-Animation abspielen
    }
  }      
}

Leider passiert nichts, wenn ich mit der Maus auf das Panel klicke :(
Auf dem Screenshot sieht man, dass die Animation schon mal korrekt ist:

So sieht der Animator-Controller aus:
(Komischerweise scheint die Vorschau unten rechts nicht zu funktionieren - sie wird abgespielt, es passiert aber nichts.)

Ziel ist, dass beim Klick/Touch auf das Panel die Animation abgespielt wird, so dass alle Buttons ausgeblendet werden.

Danke nochmal für eure Hilfe!

unityAnimation.png

UnityAnimation2.png

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...