Unity Engine: Wie kann ich das Spiel stoppen (im Code)?

1 Antwort

Vom Fragesteller als hilfreich ausgezeichnet

Hi!

Zu 1:

Genau, Du kannst für diesen Anwendungsfall wunderbar OnBecameInvisible benutzen. Du musst nur aufpassen, dass das eben für alle Richtungen gilt. Wenn Du es weiter einschränken willst, müsstest Du schon ob die y-Koordinate Deines GameObjects kleiner ist, als die sichtbare y-Koordinate Deiner Kamera. Alternativ, wenn's ganz einfach sein soll: Ein Trigger-Collider unterhalb der Map. Wenn der Ball dort ankommt, Deine Logik ausführen.

Das Spiel kannst Du mit timeScale = 0 anhalten. Ich hab mir das Tutorial angeschaut und so wie es entwickelt ist, sollte das funktionieren. Bist du sicher, dass es aufgerufen wird?

Und Achtung: Du hast OnBecomeInvisible geschrieben. Die Methode heißt aber OnBecameInvisible (Vergangenheitsform). Ich tippe daher, dass das Dein Problem sein könnte.

Zu 2:

Du könntest ein weiteres, leeres GameObject erzeugen, den BlockManager und dort folgendes Script drauf legen:

public class BlockManager : MonoBehavior {
  // Block ist das Script aus dem Tutorial
  private List<Block> _blocks = new List<Block>();

  public void AddBlock(Block block) {
    _blocks.Add(block);
  }

  public void RemoveBlock(Block block) {
    _blocks.Remove(block);

    if (_blocks.Count == 0) {
      GameOver();
    }
  }

  private void GameOver() {
    // Spiel vorbei, neues Level laden, siehe Punkt 3
  }
}

Dann erweiterst Du Script Block wie folgt:

public class Block : MonoBehavior {
  // alles andere aus dem Tutorial...

  private BlockManager _blockManager;

  private void Awake() {
    _blockManager = FindObjectOfType<BlockManager>();
    _blockManager.AddBlock(this);
  }

  private void OnDestroy() {
    _blockManager.RemoveBlock(this);
  }
}

Der Ablauf ist wie folgt: Sobald das Spiel startet, ruft Unity automatisch die Methode Awake auf. Das registriert jeden Block bei einem Manager. OnDestroy wird aufgerufen, sobald das Objekt zerstört wird (durch Dein OnCollisionEnter2D) und meldet daraufhin den Block bei dem Manager wieder ab. Wurde der letzte Block entfernt, ist die Liste vom Manager leer und dann ruft er die Methode GameOver auf.

Zu 3:

Du kannst zum Start einfach eine neue Szene machen mit einem neuen Level. In GameOver kannst Du dann über SceneManager.LoadScene("NameDerScene") das nächste Level laden.

Als kleiner "Pro-Tipp": Bei so einem Spiel wie Arkanoid würde man nicht pro Level eine eigene Szene machen, sondern man würde die Information über die Blöcke in einer Datei ablegen und die Levels aus einer Datei laden. Aber irgendwo muss man ja anfangen. :-)

Woher ich das weiß:Berufserfahrung
RBM1992 
Fragesteller
 27.08.2020, 12:32

Danke, das hat soweit alles funktioniert. Beim Stoppen einen Buchstaben verwechselt und schon funktioniert es nicht :)

Ich habe jetzt nur ein kleines Problem: Wenn das nächste Level geladen wurde, ist das Spiel automatisch gestoppt. Wie kann ich das Spiel wieder starten? Ich verwende im 2. Level die gleichen Scripte, wie im ersten. Wenn ich also ein weiteres Level hätte bzw. das zweite das Ende wäre, müsste ich in der GameOver-Methode das doch auch irgendwie feststellen können, oder? Oder muss ich für jedes Level einen eigenen BlockManager schreiben?

Danke auch für den Profi-Tipp. Fürs Erste werde ich eher mit den einzelnen Szenen arbeiten. Das Andere ist im Moment noch nicht innerhalb dessen, was ich über Unity weiß ;-) In WinForms und Konsolenanwendungen unter Windows mit .Net ist das alles irgendwie einfacher für mich xD

0
BoundfoxStudios  27.08.2020, 15:52
@RBM1992

Du musst natürlich beim Wechseln des Levels Time.timeScale auf 1 zurück setzen. Solche Einstellungen sind szenenübergreifend. Das kannst du zum Beispiel direkt vor dem Aufruf von LoadScene machen. Oder du machst es in der Awake-Methode vom BlockManager.

Oder du schreibst dir noch ein Skript, was das Management von Level und Zeit übernimmt. :-)

1
RBM1992 
Fragesteller
 28.08.2020, 12:40
@BoundfoxStudios

Danke, es hat funktioniert. Habe mir jetzt eine weitere Klasse hinzugefügt, die zu einem weiteren leeren GameObject gehört. Hier gibt es eine öffentliche statische Methode, die den Teil mit dem GameOver regelt. Diese ruft wiederum eine private statische Methode auf, die das Level ändert, bevor es aufgerufen wird (über eine String-Variable). Die neue Klasse ruft in ihrer Awake-Methode dann DontDesrtoyOnLoad(this) auf.

1