Jump to content
Unity Insider Forum

selbe Variable in verschiedenen Szenen


Timbo3

Recommended Posts

Hallo Forum.

Ich hab in meinem Spiel im ui ein Mute Knopf eingebaut. Wenn man den drückt wechselt das Bild von Lautlos auf normal und andersrum. In einer anderen Szene ist der Knopf auch. Wenn ich aber in der einen Szene den Mute Knopf gedrückt habe und ein Lautsprecher ohne Ton angezeigt wird ist er in der andern Szene wieder auf Laut. Wie kann ich machen, dass der Knopf auf Laut oder Lautlos bleibt?

PlayerPrefs geht nicht ein static Variable auch nicht(was bringen die eigentlich ich hab nur gelesen, dass der Wert der variable dann gleich bleibt.

Was kann ich da machen?

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 5 Stunden schrieb Timbo3:

PlayerPrefs geht nicht ein static Variable auch nicht

So ein Quatsch.

vor 5 Stunden schrieb Timbo3:

was bringen die eigentlich ich hab nur gelesen, dass der Wert der variable dann gleich bleibt

So ein Quatsch.

Statische Variablen sind nicht an Objekte gebunden, sondern an Klassen. Wenn du zwei Lichter hast kannst du eines blau färben und das andere rot. Das bedeutet, dass die Lichtfarbe keine statische Variable ist. Wäre es eine statische Variable, könntest du nur einmalig eine Farbe einstellen und die würde dann für alle Lichter gleichermaßen gelten.

Wenn du dein blaues Licht löschst, dann ist die Info, dass das Licht blau war, weg. Da Werte statischer Variablen aber nicht an Objekte gebunden sind, gehen sie auch nicht zusammen mit Objekten kaputt. Deshalb kannst du auch alle Objekte löschen (und genau das ist ein Szenenwechsel), aber der Wert bleibt trotzdem bestehen.

PlayerPrefs solltest du hier nicht nutzen, weil das zum Speichern von Werten ist, die auch nach Beenden und Neustart des Spiels noch vorhanden sein sollen. Wenn du einfach nur über einen Szenenwechsel hinaus einen Wert behalten willst, ist eine statische Variable absolut angebracht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Und auf die Frage, wie Du das Problem bzw. dessen Lösung umsetzen kannst, gibt es viele Möglichkeiten. Eine einfache wäre, das Objekt zu markieren, dass dieses bei einem Szenenwechsel nicht gelöscht wird. Ein Beispiel für "DontDestroyOnLoad" findet sich hier unten auf der Seite https://docs.unity3d.com/ScriptReference/Object.DontDestroyOnLoad.html Damit bleibt das Objekt auch bei Szenenwechsel erhalten und wenn irgendwo ein weiteres vorkommt, löscht sich dieses selbst um Duplikate zu vermeiden.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 2 Stunden schrieb devandart:

Damit bleibt das Objekt auch bei Szenenwechsel erhalten und wenn irgendwo ein weiteres vorkommt, löscht sich dieses selbst um Duplikate zu vermeiden.

Das macht DontDestroyOnLoad nicht automatisch.

Und Objekte in der neu geladenen Szene wissen erst einmal nicht, wo sie dieses besondere Objekt finden können. Deshalb muss man diese Lösung noch einen Schritt weiterdenken und entweder mit GameObject.Find suchen (IHGITT), oder man baut so ein Unity-Pseudo-Singleton, das letztendes genau eines ist: Eine statische Variable.

Warum also das ganze Objekt mit einer statischen Variable zugreifbar machen, nur damit man DontDestroyOnLoad benutzen kann, wenn man auch den dann nicht-statischen Wert in eine statische Variable packt und sich den komplexeren Zugriff sparen kann?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Jetzt weiß ich was der Fehler war: Bei den Szenen war voreingestellt , dass es auf laut gestellt ist und das Script wird nur aufgerufen, wenn man den Knopf drückt. 

Danke Sascha für die verständliche Erklärung von static Variablen.

Echt nervig, dass so ein kleiner Denkfehler soviele Probleme macht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Irgendwie schaffe ich es trotzdem nicht.

wie Soll ich den Zugriff auf die Variable und ie knöpfe herstellen?

using UnityEngine;

public class refresh : MonoBehaviour
{
    public GameObject muteon;
    public GameObject muteoff;
    //GameObject muteon = GameObject.Find("muteon");
    //GameObject muteoff = GameObject.Find("muteoff");
    public static bool mute;
    void Start()
    {

        if (mute)
        {
            mute = false;
            muteon.SetActive(false);
            muteoff.SetActive(true);

        }

        else if (mute == false)
        {
            mute = true;
            muteon.SetActive(true);
            muteoff.SetActive(false);
        }
    }


}

in Unity kommet dann:

NullReferenceException: Object reference not set to an instance of an object
refresh.Start () (at Assets/refresh.cs:23)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Du kannst so etwas an deinen Button hängen (oder was du sonst zum Umschalten benutzt):

public class SoundMute : MonoBehaviour
{
  public static bool mute = false;
  
  public void SetMute(bool muteOn)
  {
    mute = muteOn;
  }
}

und dann SetMute mit dem Event des UI-Elements aufrufen. Oder womit auch immer.

Dann kannst du so etwas auf deine Kamera packen, oder wo auch immer du den AudioListener hast:

[RequireComponent(typeof(AudioListener))]
public class MuteAudioListener
{
  private void Start()
  {
    if (SoundMute.mute)
    {
      GetComponent<AudioListener>().volume = 0;
    }
  }
}

Hier siehst du auch, dass man auf statische Variablen (wie auch Methoden) zugreifen kann, indem man den Klasennamen verwendet, weil es eben nicht um ein spezifisches Objekt vom Typ "SoundMute" geht.

Allgemein sei noch gesagt, dass es bei diesem spezifischen Anwendungsfall auf jeden Fall empfehlenswert ist, sich mit AudioMixer Groups auseinanderzusetzen. Damit gehen solche Sachen und noch vieles mehr extrem unproblematisch, ist ein sehr gutes System. Lohnt sich sicherlich trotzdem, das hier noch zum Üben zum Laufen zu kriegen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Noch ne Frage: Undzwar habe ich für das Spiel den Audio Manager von Brakeys nachprogrammiert und weiß jetzt nicht wie ich den Ton abschalten soll. Hier der Code:

using UnityEngine.Audio;
using UnityEngine;
using System;

public class AudioManeger : MonoBehaviour
{

    public Sound[] sounds;

    public static AudioManeger instance;

    void Awake()
    {
        if(instance == null)
        {
            instance = this;
        }
        else
        {
            Destroy(gameObject);
            return;
        }

        DontDestroyOnLoad(gameObject);

        foreach (Sound s in sounds)
        {
            s.source = gameObject.AddComponent<AudioSource>();
            s.source.clip = s.clip;
            s.source.volume = s.volume;
            s.source.pitch = s.pitch;
            s.source.loop = s.loop;
            s.source.mute = Mute.mute;

        }
    }
    void Start()
    {
        Play("Theme");
    }
    public void Play(string name)
    {
        Sound s = Array.Find(sounds, Sound => Sound.name == name);
        if(s == null)
        {
            return;
        }
        s.source.Play();

    }

}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hier ist mal die Übersicht, welche Properties und welche Methoden die AudioSource alles hat:

https://docs.unity3d.com/ScriptReference/AudioSource.html

Wenn du runter scrollst, siehst du dass es nicht nur einen Play-Befehl sondern auch einen Stop-Befehl gibt.
Ja und dann machste dir einfach eine Methode die Stop heisst, die fast genauso aussieht wie deine Play-Methode. Aber eben mit "Stop" anstatt "Play".

Link zu diesem Kommentar
Auf anderen Seiten teilen

Du solltest duich mit dem Thema "Variablen von mehreren Objekten nutzen lassen" auf jeden Fall auseinandersetzen, aber das Script, das du da von Brackeys hast, ist echt nicht sonderlich gut. Ich empfehle wirklich, dass du dir stattdessen für diesen Kontext mal AudioMixer Groups ansiehst.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...