Menu
CoddyTech

El valor nulo de Unity

Parte de la sección Fundamentos de scripting en Unity del Journey de Unity de Coddy. Lección 46 de 67.

Un objeto de Unity tiene dos mitades: el objeto de C# que conserva tu script y el objeto del motor que hay detrás. Destroy(obj) elimina la mitad del motor al final del fotograma, pero tu variable sigue apuntando a la mitad de C#, así que, en términos de C# puro, no es null. Unity redefine == para contemplar esto: una vez que se destruye el objeto, obj == null es true, al igual que la prueba breve !obj. Esto es el null falso de Unity.

?., ?? e is null no usan ese ==. Comprueban la referencia de C#, que aún existe, así que permiten que se realice la llamada, y acceder al objeto destruido provoca MissingReferenceException: The object of type 'Transform' has been destroyed but you are still trying to access it. Esta etiqueta muestra el nombre del líder de la carrera, que puede quedar fuera de juego (ser destruido):

[SerializeField] private Transform leader;

void Update()
{
    // lanza una excepción cuando se destruye leader: string shown = leader?.name ?? "nobody";
    string shown = leader != null ? leader.name : "nobody";
    Debug.Log("Leader: " + shown);
}

Para cualquier cosa que provenga de UnityEngine.Object (GameObjects, componentes, tus scripts), comprueba con == null, != null o if (obj), y reserva ?. y ?? para objetos de C# puros, como las cadenas. Recuerda también que Destroy espera hasta el final del fotograma: hasta entonces, el objeto sigue vivo y == null es false.

challenge icon

Desafío

Intermedio

El dron persigue a su objetivo, y el objetivo se destruye 2 segundos después de comenzar el juego. A partir de entonces, la Consola se llena de MissingReferenceException, porque target?.position no detecta que el objetivo ha desaparecido.

Corrige Update() con la propia comprobación de null de Unity: mientras el objetivo exista, el dron vuela hacia él a speed; una vez que se destruye, el dron se queda donde está, sin errores.

Pulsa Play y observa la Consola, corrige el script y, después, pulsa Check.

Pruébalo tú mismo

using UnityEngine;

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

    void Start()
    {
        Destroy(target.gameObject, 2f);   // el objetivo se destruye después de 2 segundos
    }

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

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Fundamentos de scripting en Unity