Il null di Unity
Fa parte della sezione Fondamenti di scripting in Unity del percorso Unity di Coddy. Lezione 46 di 67.
Un oggetto Unity ha due parti: l'oggetto C# a cui fa riferimento il tuo script e l'oggetto del motore che si trova dietro. Destroy(obj) rimuove la parte del motore alla fine del frame, ma la tua variabile punta ancora alla parte C#, quindi in termini di C# puro non è null. Unity esegue l'override di == per gestire questo caso: una volta distrutto l'oggetto, obj == null è true, così come il test breve !obj. Questo è il null fittizio di Unity.
?., ?? e is null non usano quel ==. Verificano il riferimento C#, che esiste ancora, quindi consentono la chiamata; accedere all'oggetto distrutto genera MissingReferenceException: The object of type 'Transform' has been destroyed but you are still trying to access it. Questa etichetta mostra il nome del leader della gara, che può essere eliminato (distrutto):
[SerializeField] private Transform leader;
void Update()
{
// genera un'eccezione quando leader viene distrutto: string shown = leader?.name ?? "nobody";
string shown = leader != null ? leader.name : "nobody";
Debug.Log("Leader: " + shown);
}Per qualsiasi cosa che provenga da UnityEngine.Object (GameObjects, componenti, i tuoi script), verifica con == null, != null o if (obj), e usa ?. e ?? per gli oggetti C# puri, come le stringhe. Ricorda anche che Destroy attende la fine del frame: fino ad allora, l'oggetto è ancora vivo e == null è false.
Sfida
MedioIl drone insegue il suo bersaglio, che viene distrutto dopo 2 secondi dall'inizio del gioco. Da quel momento, la Console si riempie di MissingReferenceException, perché target?.position non si accorge che il bersaglio non c'è più.
Correggi Update() usando il test di null di Unity: finché il bersaglio esiste, il drone vola verso di esso a speed; una volta distrutto, il drone resta dov'è, senza errori.
Premi Play e osserva la Console, correggi lo script, poi premi Check.
Provalo tu
using UnityEngine;
public class Chaser : MonoBehaviour
{
[SerializeField] private Transform target;
[SerializeField] private float speed = 2f;
void Start()
{
Destroy(target.gameObject, 2f); // target viene distrutto dopo 2 secondi
}
void Update()
{
Vector3 goal = target?.position ?? transform.position;
transform.position = Vector3.MoveTowards(transform.position, goal, speed * Time.deltaTime);
}
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Fondamenti di scripting in Unity
1Il tuo primo script
Ciao, UnityPosiziona il cuboMuovi a ogni frameRuota ogni secondoGuida con i tastiRiepilogo: guida il cubo4Vettori
Sommare vettoriDirezioniSpazio locale e spazio globaleVelocità diagonaleDistanza tra gli oggettiVector3 è una structRiepilogo: pilota di droni7Progetto: Acchiappa la stella
L'acchiappatoreUna stella cadente10Il ciclo di vita degli script
Awake e StartUpdate e LateUpdateOnEnable e OnDisableL’ordine del ciclo di vitaRipasso: logger del ciclo di vita2L'Inspector
Campi dell'InspectorSerializeFieldNumeri decimali e MathfAttributi dell'InspectorRiepilogo: Ascensore5Trasformazioni e gerarchia
Genitori e figliScalaGuarda gli oggettiMuoversi verso un puntoRiepilogo: Luna in orbita8Trovare gli oggetti
Trova per nomeTagTrova per tipoI riferimenti sono meglio di FindIl null di UnityRipasso: la moneta più vicina6Oggetti di gioco e componenti
Riferimenti nell’InspectorOttenere un componenteComponenti mancantiAggiungere un componenteRequireComponentMostrare e nascondereRipasso: interruttore della luce