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.
Desafio
MédioO 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);
}
}
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
1Seu primeiro script
Olá, UnityPosicione o cuboMova a cada quadroGire a cada segundoConduza com as teclasRecapitulando: dirija o cubo4Vetores
Adicionando vetoresDireçõesEspaço local e espaço do mundoVelocidade diagonalDistância entre objetosVector3 é uma structRevisão: piloto de drone7Projeto: Pegue a Estrela
O ApanhadorUma Estrela Cadente10O ciclo de vida dos scripts
Awake e StartUpdate e LateUpdateOnEnable e OnDisableA ordem do ciclo de vidaRevisão: registrador do ciclo de vida5Transformações e Hierarquia
Pais e FilhosEscalaObserve as CoisasMova-se em Direção a um PontoRevisão: Lua em Órbita8Encontrando coisas
Encontrar por nomeTagsEncontrar por tipoReferências vencem FindO null do UnityRevisão: moeda mais próxima6GameObjects e Componentes
Referências no InspectorObter um ComponenteComponentes AusentesAdicionar um ComponenteRequireComponentMostrar e OcultarRevisão: Interruptor de Luz