Null w Unity
Część sekcji Podstawy skryptów w Unity ścieżki Unity w Coddy. Lekcja 46 z 67.
Obiekt Unity ma dwie części: obiekt C#, który przechowuje Twój skrypt, oraz znajdujący się za nim obiekt silnika. Destroy(obj) usuwa część silnika na koniec klatki, ale Twoja zmienna nadal wskazuje na część C#, więc w zwykłym C# nie ma ona wartości null. Unity przeciąża operator ==, aby to uwzględnić: po zniszczeniu obiektu obj == null ma wartość true, podobnie jak krótki test !obj. To właśnie Unity nazywa fałszywym null.
?., ?? i is null nie używają tego ==. Sprawdzają referencję C#, która nadal istnieje, więc pozwalają wykonać wywołanie, a odwołanie się do zniszczonego obiektu powoduje wyjątek MissingReferenceException: The object of type 'Transform' has been destroyed but you are still trying to access it. Ta etykieta pokazuje nazwę lidera wyścigu, który może zostać wyeliminowany (zniszczony):
[SerializeField] private Transform leader;
void Update()
{
// zgłasza wyjątek, gdy leader zostanie zniszczony: string shown = leader?.name ?? "nobody";
string shown = leader != null ? leader.name : "nobody";
Debug.Log("Leader: " + shown);
}W przypadku wszystkiego, co pochodzi z UnityEngine.Object (GameObjects, komponentów, Twoich skryptów), sprawdzaj == null, != null lub if (obj), a ?. i ?? zostaw dla zwykłych obiektów C#, takich jak ciągi znaków. Pamiętaj też, że Destroy czeka do końca klatki: do tego czasu obiekt nadal istnieje, a == null ma wartość false.
Wyzwanie
ŚredniDron ściga swój cel, a cel zostaje zniszczony po 2 sekundach gry. Od tego momentu konsola zapełnia się błędami MissingReferenceException, ponieważ target?.position nie wykrywa, że celu już nie ma.
Popraw Update(), używając własnego testu null w Unity: gdy cel istnieje, dron leci w jego stronę z prędkością speed; gdy zostanie zniszczony, dron pozostaje w miejscu i nie pojawiają się żadne błędy.
Naciśnij Play i obserwuj konsolę, popraw skrypt, a następnie naciśnij Check.
Spróbuj swoich sił
using UnityEngine;
public class Chaser : MonoBehaviour
{
[SerializeField] private Transform target;
[SerializeField] private float speed = 2f;
void Start()
{
Destroy(target.gameObject, 2f); // target zostaje zniszczony po 2 sekundach
}
void Update()
{
Vector3 goal = target?.position ?? transform.position;
transform.position = Vector3.MoveTowards(transform.position, goal, speed * Time.deltaTime);
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Podstawy skryptów w Unity
1Twój pierwszy skrypt
Witaj, UnityUmieść sześcianPoruszaj się w każdej klatceObracaj się co sekundęSteruj za pomocą klawiszyPodsumowanie: Prowadź sześcian2Inspektor
Pola inspektoraSerializeFieldLiczby zmiennoprzecinkowe i MathfAtrybuty inspektoraPodsumowanie: Winda5Transformacje i hierarchia
Rodzice i dzieciSkalaPatrz na obiektyPoruszanie się w kierunku punktuPodsumowanie: Księżyc krążący po orbicie8Wyszukiwanie obiektów
Wyszukiwanie po nazwieTagiWyszukiwanie po typieReferencje lepsze niż FindNull w UnityPodsumowanie: najbliższa moneta3Wejście
Naciśnięty, przytrzymany, zwolnionyOsiePrzyciski o nazwachPrzyciski myszyPowtórka: naładowany skok6Obiekty gry i komponenty
Referencje w InspectorzePobieranie komponentuBrakujące komponentyDodawanie komponentuRequireComponentPokazywanie i ukrywaniePodsumowanie: włącznik światła