Unitys Null
Teil des Abschnitts Grundlagen des Scripting in Unity der Unity-Journey von Coddy. Lektion 46 von 67.
Ein Unity-Objekt hat zwei Hälften: das C#-Objekt, das dein Skript hält, und das Engine-Objekt dahinter. Destroy(obj) entfernt die Engine-Hälfte am Ende des Frames, aber deine Variable verweist weiterhin auf die C#-Hälfte, daher ist sie im Sinne von reinem C# nicht null. Unity überschreibt ==, um dies abzudecken: Sobald das Objekt zerstört ist, ist obj == null wahr, ebenso wie der kurze Test !obj. Das ist Unitys Fake Null.
?., ?? und is null verwenden dieses == nicht. Sie prüfen die C#-Referenz, die weiterhin existiert, sodass sie den Aufruf zulassen; der Zugriff auf das zerstörte Objekt löst dann MissingReferenceException: The object of type 'Transform' has been destroyed but you are still trying to access it. aus. Dieses Label zeigt den Namen des Rennführenden an, der aus dem Rennen geworfen (zerstört) werden kann:
[SerializeField] private Transform leader;
void Update()
{
// wirft eine Ausnahme, sobald leader zerstört wird: string shown = leader?.name ?? "nobody";
string shown = leader != null ? leader.name : "nobody";
Debug.Log("Leader: " + shown);
}Bei allem, was von UnityEngine.Object stammt (GameObjects, Komponenten, deine Skripte), solltest du mit == null, != null oder if (obj) prüfen und ?. und ?? für reine C#-Objekte wie Zeichenfolgen verwenden. Denk außerdem daran, dass Destroy bis zum Ende des Frames wartet: Bis dahin lebt das Objekt noch und == null ist false.
Aufgabe
MittelDie Drohne verfolgt ihr Ziel, und das Ziel wird 2 Sekunden nach Spielbeginn zerstört. Von da an füllt sich die Console mit MissingReferenceException, weil target?.position nicht erkennt, dass das Ziel verschwunden ist.
Behebe Update() mit Unitys eigenem Nulltest: Solange das Ziel existiert, fliegt die Drohne mit speed darauf zu; sobald es zerstört ist, bleibt die Drohne an Ort und Stelle, ohne Fehler.
Drücke Play und beobachte die Console, behebe das Skript und klicke dann auf Check.
Probier es selbst
using UnityEngine;
public class Chaser : MonoBehaviour
{
[SerializeField] private Transform target;
[SerializeField] private float speed = 2f;
void Start()
{
Destroy(target.gameObject, 2f); // Das Ziel wird nach 2 Sekunden zerstört
}
void Update()
{
Vector3 goal = target?.position ?? transform.position;
transform.position = Vector3.MoveTowards(transform.position, goal, speed * Time.deltaTime);
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Grundlagen des Scripting in Unity
1Dein erstes Skript
Hallo, UnityPlatziere den WürfelBewege dich in jedem FrameDrehe dich jede SekundeSteuere mit den TastenRückblick: Steuere den Würfel4Vektoren
Vektoren addierenRichtungenLokaler und globaler RaumDiagonale GeschwindigkeitAbstand zwischen ObjektenVector3 ist ein StructRückblick: Drohnenpilot7Projekt: Fang den Stern
Der FängerEin fallender Stern10Der Lebenszyklus eines Skripts
Awake und StartUpdate und LateUpdateOnEnable und OnDisableDie Reihenfolge im LebenszyklusRückblick: Lifecycle Logger5Transformationen und Hierarchie
Eltern und KinderSkalierungDinge ansehenAuf einen Punkt zubewegenRückblick: Umlaufender Mond8Dinge finden
Nach Namen findenTagsNach Typ findenReferenzen schlagen FindUnitys NullRückblick: Nächste Münze11Projekt: Weiche den Blöcken aus
Der LäuferFallende Blöcke6GameObjects und Komponenten
Referenzen im InspectorEine Komponente abrufenFehlende KomponentenEine Komponente hinzufügenRequireComponentEin- und AusblendenRückblick: Lichtschalter