Menu
CoddyTech

Il null di Unity

Fa parte della sezione Fondamenti di scripting in Unity del percorso Unity di Coddy. Lezione 60 di 85.

Un oggetto Unity ha due parti: l’oggetto C# che il tuo script conserva 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# semplice non è null. Unity esegue l’override di == per gestire questo caso: una volta distrutto l’oggetto, obj == null è true, così come il controllo breve !obj. Questo è il null fittizio di Unity.

?., ?? e is null non usano quel ==. Controllano il riferimento C#, che esiste ancora, quindi consentono la chiamata, e 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 oggetto che proviene da UnityEngine.Object (GameObject, componenti, i tuoi script), verifica con == null, != null o if (obj), e usa ?. e ?? per gli oggetti C# semplici, 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

Interrompi gli errori del drone quando il suo bersaglio viene distrutto.

  1. In Update(), sostituisci entrambe le righe con if (target != null), il controllo null di Unity.
  2. Al suo interno, scrivi transform.position = Vector3.MoveTowards(transform.position, target.position, speed * Time.deltaTime);.

Premi «Gioca»: il drone insegue il bersaglio, poi resta in attesa senza errori nella Console. Poi premi «Verifica».

Provalo tu

using UnityEngine;

public class Chaser : MonoBehaviour
{
    [SerializeField] private Transform target;
    [SerializeField] private float speed = 2f;

    void Start()
    {
        Destroy(target.gameObject, 2f);   // il target viene distrutto dopo 2 secondi
    }

    void Update()
    {
        Vector3 goal = target?.position ?? transform.position;
        transform.position = Vector3.MoveTowards(transform.position, goal, speed * Time.deltaTime);
    }
}

Tutte le lezioni di Fondamenti di scripting in Unity

Esercitati da solo: Playground Unity