Menu
CoddyTech

O null do Unity

Parte da seção Noções básicas de scripting no Unity do Journey de Unity da Coddy. Lição 46 de 67.

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 final do quadro, mas sua variável ainda aponta para a parte C#, então, em termos de C# puro, ela não é nula. O Unity sobrescreve == para lidar com isso: depois que o objeto é destruído, obj == null é verdadeiro, assim como o teste curto !obj. Isso é o null falso do Unity.

?., ?? e is null não usam esse ==. Eles testam a referência C#, que ainda existe, então permitem a chamada, 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 nocauteado (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 deixe ?. e ?? para objetos C# comuns, como strings. Lembre-se também de que Destroy aguarda o final do quadro: até lá, o objeto continua vivo e == null é falso.

challenge icon

Desafio

Médio

O drone persegue seu alvo, e o alvo é destruído 2 segundos após o início do jogo. A partir daí, o Console fica cheio de MissingReferenceException, porque target?.position não percebe que o alvo desapareceu.

Corrija Update() usando o próprio teste de null do Unity: enquanto o alvo existir, o drone voa em direção a ele com speed; depois que ele for destruído, o drone fica onde está, sem erros.

Pressione Play e observe o Console, corrija o script e, em seguida, Check.

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);
    }
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Noções básicas de scripting no Unity