Das Singleton
Teil des Abschnitts Echte Spiele entwickeln der Unity-Journey von Coddy. Lektion 13 von 56.
Eine Inspector-Referenz braucht ein Objekt, auf das du etwas ziehen kannst. Gegner, die ein Spawner während des Spiels erstellt, stammen aus einem Prefab, und ein Prefab kann nur auf Assets und auf seine eigenen Bestandteile verweisen, niemals auf ein Objekt in einer Szene. Deshalb ist sein GameManager-Feld leer. Die übliche Lösung ist ein Singleton: Der GameManager speichert sich selbst in einem Feld, auf das jedes Skript über den Klassennamen zugreifen kann.
public class GameManager : MonoBehaviour
{
public static GameManager Instance;
private int kills;
void Awake()
{
Instance = this;
}
public void EnemyDown()
{
kills++;
Debug.Log("Kills: " + kills);
}
}// Enemy.cs, auf dem Gegner-Prefab
public void Die()
{
GameManager.Instance.EnemyDown();
Destroy(gameObject);
}static bedeutet, dass das Feld zur Klasse gehört, nicht zu einem Objekt. Jedes GameManager-Objekt hätte ein eigenes kills, aber im ganzen Spiel gibt es nur eine Instance, und du erreichst sie über den Klassennamen: GameManager.Instance. Jedes Skript kann darauf zugreifen, auch ein Gegner, der vor einer Minute gespawnt wurde, ohne dass ein eigenes Feld ausgefüllt werden muss.
Der Manager setzt Instance = this; in Awake, wobei this das Skript selbst ist. Unity führt jedes Awake in der Szene aus, bevor irgendein Start ausgeführt wird. Deshalb können andere Skripte ab ihrem Start GameManager.Instance verwenden. Ein zweiter GameManager in der Szene würde Instance mit sich selbst überschreiben; im Kapitel „Scenes and Levels“ wird gezeigt, wie du das verhinderst.
Aufgabe
EinfachMeteore regnen herab. Der Spawner lässt alle 1.5 Sekunden einen Meteor aus einem Prefab fallen, die Pfeiltasten bewegen den Player und der GameManager zählt einen abgefangenen Meteor mit MeteorCaught() und einen Meteor, der den Boden trifft, mit MeteorLanded(). Diese Skripte sind bereit.
Das Meteor-Skript meldet Ereignisse über sein game-Feld, aber die Meteore stammen aus einem Prefab, daher ist game leer und jede Meldung schlägt fehl. Behebe das mit einem Singleton:
- Füge in
GameManager.csein öffentliches statisches FeldInstancevom Typ GameManager hinzu und setze es in Awake auf dieses Skript. - Lösche in
Meteor.csdas Feldgameund melde Ereignisse stattdessen überGameManager.Instance.
Drücke Play, fange ein paar Meteore ab und lass ein paar durch, dann Check.
Probier es selbst
using UnityEngine;
using TMPro;
public class GameManager : MonoBehaviour
{
public TMP_Text caughtText;
public TMP_Text shieldText;
private int caught;
private int shield = 3;
public void MeteorCaught()
{
caught++;
caughtText.text = "Caught: " + caught;
}
public void MeteorLanded()
{
shield--;
shieldText.text = "Shield: " + shield;
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Echte Spiele entwickeln
1Text auf dem Bildschirm
Canvas und TextPunktestand anzeigenZahlen formatierenEin Countdown-TimerRückblick: Tachometer4Szenen und Level
Eine Szene ladenDas Level neu startenNächstes LevelZwischen Szenen beibehaltenRückblick: Levelauswahl10Projekt: 3D-Plattformer
Der ParcoursBewegliche Plattformen2Buttons und Bildschirme
Buttons und onClickLambdasVerknüpfungen im InspectorPanels ein- und ausblendenGesundheitsbalkenRückblick: Upgrade-Shop5Speichern mit PlayerPrefs
Eine Zahl speichernMit einem Standardwert ladenHöchstpunktzahlEinstellungen speichernRückblick: Münzen auf der Bank3Der Spielmanager
Ein Skript steuert das SpielDas SingletonSpielzuständeZum Zustand wechselnRückblick: Rundenmanager