Menu
CoddyTech

El null de Unity

Parte de la sección Fundamentos de scripting en Unity del Journey de Unity de Coddy. Lección 60 de 85.

Un objeto de Unity tiene dos partes: el objeto de C# que conserva tu script y el objeto del motor que hay detrás. Destroy(obj) elimina la parte del motor al final del fotograma, pero tu variable sigue apuntando a la parte de C#, así que, en términos de C# puro, no es null. Unity redefine == para contemplar esto: una vez destruido el objeto, obj == null es true, y la prueba abreviada !obj también. 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 ejecute la llamada, y acceder al objeto destruido lanza 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 ser eliminado (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# puro, 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

Detén los errores del dron cuando se destruya su objetivo.

  1. En Update(), reemplaza ambas líneas por if (target != null), la comprobación de nulo propia de Unity.
  2. Dentro de esta, escribe transform.position = Vector3.MoveTowards(transform.position, target.position, speed * Time.deltaTime);.

Pulsa «Jugar»: el dron persigue al objetivo y después espera sin errores en la Consola. Luego pulsa «Comprobar».

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);
    }
}

Todas las lecciones de Fundamentos de scripting en Unity

Practica por tu cuenta: Playground de Unity