Menu
CoddyTech

O null do Unity

Parte da seção Fundamentos de Scripting no Unity do Journey de Unity da Coddy. Lição 60 de 85.

Um objeto do Unity tem duas partes: o objeto C# que seu script mantém e o objeto do mecanismo por trás dele. Destroy(obj) remove a parte do mecanismo no fim do quadro, mas sua variável ainda aponta para a parte C#, então, em termos de C# puro, ela não é null. O Unity sobrescreve == para lidar com isso: depois que o objeto é destruído, obj == null é verdadeiro, assim como o teste curto !obj. Esse é o null falso do Unity.

?., ?? e is null não usam esse ==. Eles verificam a referência C#, que ainda existe, então permitem que a chamada prossiga, e acessar o objeto destruído gera MissingReferenceException: The object of type 'Transform' has been destroyed but you are still trying to access it. Este rótulo mostra o nome do líder da corrida, que pode ser eliminado (destruído):

[SerializeField] private Transform leader;

void Update()
{
    // lança uma exceção quando leader é destruído: string shown = leader?.name ?? "nobody";
    string shown = leader != null ? leader.name : "nobody";
    Debug.Log("Leader: " + shown);
}

Para qualquer coisa que venha de UnityEngine.Object (GameObjects, componentes, seus scripts), teste com == null, != null ou if (obj), e reserve ?. e ?? para objetos C# comuns, como strings. Lembre-se também de que Destroy espera até o fim do quadro: até lá, o objeto continua vivo e == null é falso.

challenge icon

Desafio

Médio

Interrompa os erros do drone quando o alvo for destruído.

  1. Em Update(), substitua as duas linhas por if (target != null), o teste de nulo próprio do Unity.
  2. Dentro dele, escreva transform.position = Vector3.MoveTowards(transform.position, target.position, speed * Time.deltaTime);.

Pressione “Jogar”: o drone persegue o alvo e, em seguida, aguarda sem erros no Console. Depois, pressione “Verificar”.

Experimente você mesmo

using UnityEngine;

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

    void Start()
    {
        Destroy(target.gameObject, 2f);   // o target é destruído após 2 segundos
    }

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

Todas as lições de Fundamentos de Scripting no Unity

Pratique por conta própria: Playground de Unity