Menu
CoddyTech

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.

challenge icon

Sfida

Medio

Il 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);
    }
}
quiz iconMettiti alla prova

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