Como muitos usuários estão enfrentando o NullReferenceException: Object reference not set to an instance of an object
erro no Unity, pensei que seria uma boa idéia reunir de várias fontes algumas explicações e maneiras de corrigir esse erro.
Sintomas
Estou recebendo o erro abaixo que aparece no meu console, o que significa e como faço para corrigi-lo?
NullReferenceException: referência de objeto não definida para uma instância de um objeto
unity
exceptions
Hellium
fonte
fonte
Respostas:
Tipo de valor versus tipo de referência
Em muitas linguagens de programação, as variáveis têm o que é chamado de "tipo de dados". Os dois tipos de dados primários são os tipos de valor (int, float, bool, char, struct, ...) e o tipo de referência (instância de classes). Enquanto os tipos de valor contêm o próprio valor , as referências contêm um endereço de memória apontando para uma parte da memória alocada para conter um conjunto de valores (semelhante ao C / C ++).
Por exemplo,
Vector3
é um tipo de valor (uma estrutura que contém as coordenadas e algumas funções), enquanto os componentes anexados ao seu GameObject (incluindo seus scripts personalizados herdados deMonoBehaviour
) são do tipo de referência.Quando posso ter uma NullReferenceException?
NullReferenceException
são lançadas quando você tenta acessar uma variável de referência que não faz referência a nenhum objeto, portanto é nula (o endereço da memória está apontando para 0).Alguns lugares comuns a
NullReferenceException
serão levantados:Manipulando um GameObject / Component que não foi especificado no inspetor
Recuperando um componente que não está anexado ao GameObject e, em seguida, tentando manipulá-lo:
Acessando um GameObject que não existe:
Nota: Tenha cuidado,
GameObject.Find
,GameObject.FindWithTag
,GameObject.FindObjectOfType
retornar apenas GameObjects que são habilitados na hierarquia quando a função é chamada.Tentando usar o resultado de um getter que está retornando
null
:Acessando um elemento de uma matriz não inicializada
Menos comum, mas irritante se você não souber sobre os delegados de C #:
Como consertar ?
Se você entendeu os parágrafos anteriores, sabe como corrigir o erro: verifique se sua variável está referenciando (apontando para) uma instância de uma classe (ou contendo pelo menos uma função para delegados).
Mais fácil falar do que fazer? Sim, de fato. Aqui estão algumas dicas para evitar e identificar o problema.
A maneira "suja": o método try & catch:
O caminho "mais limpo" (IMHO): A verificação
Ao enfrentar um erro que você não pode resolver, é sempre uma boa idéia encontrar a causa do problema. Se você é "preguiçoso" (ou se o problema pode ser resolvido facilmente), use
Debug.Log
para mostrar no console informações que ajudarão você a identificar o que poderia causar o problema. Uma maneira mais complexa é usar os pontos de interrupção e o depurador do seu IDE.O uso
Debug.Log
é bastante útil para determinar qual função é chamada primeiro, por exemplo. Especialmente se você tiver uma função responsável pela inicialização dos campos. Mas não se esqueça de removê-losDebug.Log
para evitar sobrecarregar seu console (e por razões de desempenho).Outro conselho, não hesite em "cortar" suas chamadas de função e adicionar
Debug.Log
para fazer algumas verificações.Ao invés de :
Faça isso para verificar se todas as referências estão definidas:
Melhor ainda :
Fontes:
fonte
try/catch
. O erro diz muito sobre o problema que você tem lá e, antes que os iniciantes comecem a verificar nulos em todos os lugares, o principal problema está no inspetor, pois você esquece de fazer referência a algum objeto (arraste o objeto para o script). Eu já vi muitos códigos comtry/catch
e verificações nulas em lugares onde é totalmente desnecessário. Depurar e trabalhar com um código como esse é "uma dor no a **". Os iniciantes aprendem sobre os casos de uso dessas verificações e só então os usam.else
. Ter umNullReferenceException
nem sempre é auto-explicativo, enquantoNo Rigidbody component attached to the gameObject
explica diretamente o que está errado. Concordo que apenas ter aif( obj != null )
mensagem sem apenas "oculta" o problema e você pode ter um projeto funcionando, mas não fazendo o que esperaria sem saber o porquê.Embora possamos facilmente fazer uma verificação para garantir que não estamos tentando acessar uma referência nula, essa nem sempre é uma solução adequada. Muitas vezes, na programação do Unity, nosso problema pode derivar do fato de que a referência não deve ser nula. Em algumas situações, simplesmente ignorar referências nulas pode quebrar nosso código.
Por exemplo, pode ser uma referência ao nosso controlador de entrada. É ótimo que o jogo não trava devido à exceção de referência nula, mas precisamos descobrir por que não há um controlador de entrada e corrigir esse problema. Sem ele, temos um jogo que pode não travar, mas também não pode receber informações.
Abaixo, listarei possíveis razões e soluções, conforme as encontro em outras perguntas.
Você está tentando acessar uma classe "gerente"?
Se você está tentando acessar uma classe que age como um "gerente" (ou seja, uma classe que só deve ter uma instância em execução por vez), é melhor usar a abordagem Singleton . Idealmente, uma classe Singleton pode ser acessada de qualquer lugar, diretamente, mantendo uma
public static
referência a si mesma. Dessa maneira, um Singleton pode conter uma referência à instância ativa, que seria acessível sem o problema de configurar a referência real todas as vezes.Você está fazendo referência à instância do seu objeto?
É comum simplesmente marcar uma referência como
public
, para que possamos definir a referência para a instância por meio do inspetor. Sempre verifique que você já definir a referência a uma instância, através do inspector, como não é incomum perder esta etapa.Você está instanciando sua instância?
Se estivermos configurando nosso objeto no código, é importante garantir que instanciamos o objeto. Isso pode ser realizado usando a
new
palavra - chave e os métodos construtores. Por exemplo, considere o seguinte:Criamos uma referência a
GameObject
, mas não aponta para nada. O acesso a essa referência como está resultará em uma exceção de referência nula . Antes de referenciarmos nossaGameObject
instância, podemos chamar um método construtor padrão da seguinte maneira:O tutorial do Unity sobre classes explica a prática de criar e usar construtores.
Você está usando o
GetComponent<t>()
método com a suposição de que o componente existe?Primeiro, verifique se sempre chamamos
GetComponent<t>()
antes de chamar métodos da instância do componente.Por motivos que não valem a pena, podemos assumir que nosso objeto de jogo local contém um componente específico e tentar acessá-lo
GetComponent<t>()
. Se o objeto do jogo local não contiver esse componente específico, retornaremos umnull
valor.Você pode facilmente verificar se o valor retornado é
null
antes de acessá-lo. No entanto, se o seu objeto de jogo deve ter o componente necessário, pode ser melhor para garantir que pelo menos tem um padrão versão desse componente. Podemos marcar umMonoBehaviour
como[RequireComponent(typeof(t))]
para garantir que sempre tem esse tipo de componente.Aqui está um exemplo de a
MonoBehaviour
para um objeto de jogo que deve sempre conter aRigidbody
. Se o script for adicionado a um objeto de jogo que não contenha aRigidbody
, um padrãoRigidbody
será criado.Você tentou recriar seu projeto?
Existem alguns casos em que o Unity pode causar problemas ao tentar fazer referência a uma versão em cache de um objeto de jogo. De acordo com a solução antiga "desligue e ligue novamente", tente excluir a pasta Biblioteca e abra novamente o Unity. A unidade será forçada a reconstruir seu projeto. Isso pode resolver algumas instâncias muito peculiares desse problema e deve apontar para problemas que não surgiriam na versão final.
fonte
Vejo que há uma resposta aceita. Mas, há uma resposta ou sugestão melhor para você manipular
NullReferenceException
. Se você pode relacionar a programação na linguagem Java como eu, pode impedir o envio de um erro nulo usando otry-catch
bloco Experimente você mesmo! ;-)Se você estiver usando C #, verifique se possui
using System;
a parte superior do seu arquivo de script. Caso contrário, adicione-o. Agora, você pode usar todos os tipos deException
classes enquanto tenta capturar uma linha de código.Se você estiver usando o UnityScript, use
import System;
Aqui está um exemplo:
Também lembre-se, você pode pegar também outras exceções, como
MissingReferenceException
,MissingComponentException
,IndexOutOfRangeException
, ou quaisquer outras classes de exceção, desde que você incluirusing System
no seu script.Isso é tudo.
fonte