Dado que muchos usuarios se enfrentan al NullReferenceException: Object reference not set to an instance of an object
error en Unity, pensé que sería una buena idea reunir algunas fuentes y explicaciones para solucionar este error.
Síntomas
Me aparece el siguiente error en mi consola, ¿qué significa y cómo lo soluciono?
NullReferenceException: referencia de objeto no establecida en una instancia de un objeto
unity
exceptions
Hellium
fuente
fuente
Respuestas:
Tipo de valor vs tipo de referencia
En muchos lenguajes de programación, las variables tienen lo que se llama un "tipo de datos". Los dos tipos de datos principales son los tipos de valor (int, float, bool, char, struct, ...) y el tipo de referencia (instancia de clases). Mientras que los tipos de valor contienen el valor en sí , las referencias contienen una dirección de memoria que apunta a una parte de la memoria asignada para contener un conjunto de valores (similar a C / C ++).
Por ejemplo,
Vector3
es un tipo de valor (una estructura que contiene las coordenadas y algunas funciones) mientras que los componentes adjuntos a su GameObject (incluidos sus scripts personalizados que heredanMonoBehaviour
) son de tipo de referencia.¿Cuándo puedo tener una NullReferenceException?
NullReferenceException
se lanzan cuando intenta acceder a una variable de referencia que no hace referencia a ningún objeto, por lo tanto, es nula (la dirección de memoria apunta a 0).Se
NullReferenceException
plantearán algunos lugares comunes a :Manipular un GameObject / Component que no se haya especificado en el inspector
Recuperando un componente que no está conectado al GameObject y luego, tratando de manipularlo:
Acceder a un GameObject que no existe:
Nota: Tenga cuidado,
GameObject.Find
,GameObject.FindWithTag
,GameObject.FindObjectOfType
devolver sólo GameObjects que están habilitadas en la jerarquía cuando se invoca la función.Intentando usar el resultado de un getter que está regresando
null
:Acceder a un elemento de una matriz no inicializada
Menos común, pero molesto si no lo sabe sobre los delegados de C #:
Como arreglar ?
Si ha entendido los párrafos anteriores, sabe cómo corregir el error: asegúrese de que su variable haga referencia (señale) a una instancia de una clase (o que contenga al menos una función para delegados).
¿Es más fácil decirlo que hacerlo? Si, de hecho. Aquí hay algunos consejos para evitar e identificar el problema.
La forma "sucia": el método try & catch:
La forma "más limpia" (en mi humilde opinión): el cheque
Cuando enfrenta un error que no puede resolver, siempre es una buena idea encontrar la causa del problema. Si es "flojo" (o si el problema se puede resolver fácilmente), use
Debug.Log
para mostrar en la consola información que lo ayudará a identificar qué podría causar el problema. Una forma más compleja es utilizar los puntos de interrupción y el depurador de su IDE.El uso
Debug.Log
es bastante útil para determinar qué función se llama primero, por ejemplo. Especialmente si tiene una función responsable de inicializar campos. Pero no olvide eliminarlosDebug.Log
para evitar abarrotar su consola (y por razones de rendimiento).Otro consejo, no dude en "cortar" sus llamadas a funciones y agregarlas
Debug.Log
para hacer algunas verificaciones.En lugar de :
Haga esto para verificar si todas las referencias están establecidas:
Aun mejor :
Fuentes:
fuente
try/catch
. El error le dice mucho sobre el problema que tiene allí, y antes de que los principiantes comiencen a poner cheques nulos en todas partes, su problema principal está en el inspector, ya que olvida hacer referencia a algún objeto (arrastre el objeto al script). He visto mucho códigotry/catch
y comprobaciones nulas en lugares donde es totalmente innecesario. La depuración y el trabajo con un código como ese es "una molestia en el a **". Los principiantes aprenden sobre los casos de uso de esos controles y solo luego los usan.else
. Tener unNullReferenceException
no siempre se explica por sí mismo mientrasNo Rigidbody component attached to the gameObject
explica directamente lo que está mal. Estoy de acuerdo en que solo tener elif( obj != null )
mensaje sin "oculta" el problema, y puede tener un proyecto que funcione pero no hacer lo que esperaría sin saber por qué.Si bien podemos simplemente hacer una verificación para asegurarnos de que no estamos tratando de acceder a una referencia nula, esta no siempre es una solución adecuada. Muchas veces, en la programación de Unity, nuestro problema puede derivarse del hecho de que la referencia no debe ser nula. En algunas situaciones, simplemente ignorar referencias nulas puede romper nuestro código.
Por ejemplo, podría ser una referencia a nuestro controlador de entrada. Es genial que el juego no se bloquee debido a la excepción de referencia nula, pero necesitamos descubrir por qué no hay un controlador de entrada y solucionar ese problema. Sin él, tenemos un juego que puede no bloquearse, pero tampoco puede recibir información.
A continuación, enumeraré posibles razones y soluciones, a medida que las encuentre en otras preguntas.
¿Estás tratando de acceder a una clase de "gerente"?
Si está intentando acceder a una clase que actúa como un "administrador" (es decir, una clase que solo debería tener una instancia ejecutándose a la vez), es mejor que utilice el enfoque Singleton . Se puede acceder idealmente a una clase Singleton desde cualquier lugar, directamente, manteniendo una
public static
referencia a sí misma. De esta manera, un Singleton puede contener una referencia a la instancia activa, que sería accesible sin la molestia de configurar la referencia real cada vez.¿Estás haciendo referencia a la instancia de tu objeto?
Es común simplemente marcar una referencia como
public
, por lo que podemos establecer la referencia a la instancia a través del inspector. Compruebe siempre que haya establecido la referencia a una instancia, a través del inspector, ya que no es raro que se salte este paso.¿Estás instanciando tu instancia?
Si estamos configurando nuestro objeto en código, es importante asegurarse de crear una instancia del objeto. Esto puede llevarse a cabo utilizando la
new
palabra clave y los métodos de construcción. Por ejemplo, considere lo siguiente:Hemos creado una referencia a a
GameObject
, pero no apunta a nada. Acceder a esta referencia como está dará como resultado una excepción de referencia nula . Antes de hacer referencia a nuestraGameObject
instancia, podemos llamar a un método de constructor predeterminado de la siguiente manera:El tutorial de Unity sobre clases explica la práctica de crear y usar constructores.
¿Está utilizando el
GetComponent<t>()
método con el supuesto de que el componente existe?Primero, asegúrese de que siempre llamemos
GetComponent<t>()
antes de llamar a los métodos desde la instancia del componente.Por razones por las que no vale la pena entrar, podemos suponer que nuestro objeto de juego local contiene un componente en particular y tratar de acceder a él
GetComponent<t>()
. Si el objeto del juego local no contiene ese componente en particular, devolveremos unnull
valor.Puede verificar fácilmente si el valor de retorno es
null
, antes de acceder a él. Sin embargo, si su objeto de juego debe tener el componente requerido, puede ser mejor asegurarse de que al menos tenga una versión predeterminada de ese componente. Podemos etiquetar unaMonoBehaviour
como[RequireComponent(typeof(t))]
para asegurar que siempre tenemos ese tipo de componente.Aquí hay un ejemplo de un
MonoBehaviour
objeto para un juego que siempre debe contener unRigidbody
. Si el script se agrega a un objeto del juego que no contiene unRigidbody
, seRigidbody
creará un valor predeterminado .¿Has intentado reconstruir tu proyecto?
Hay algunos casos en los que Unity puede causar problemas al intentar hacer referencia a una versión en caché de un objeto de juego. En línea con la antigua solución de "apagar y volver a encender", intente eliminar su carpeta Biblioteca y vuelva a abrir Unity. Unity se verá obligado a reconstruir su proyecto. Esto puede resolver algunos casos muy peculiares de este problema, y debería apuntar a problemas que no aparecerían en una compilación final.
fuente
Veo que hay una respuesta aceptada. Pero, hay una mejor respuesta o sugerencia para usted para el manejo
NullReferenceException
. Si puede relacionar la programación en lenguaje Java como yo, puede evitar enviar un error nulo utilizando eltry-catch
bloque. Pruébalo por ti mismo! ;-)Si está utilizando en C #, verifique si tiene
using System;
en la parte superior de su archivo de script. Si no, agréguelo. Ahora, puede usar todo tipo deException
clases mientras intenta atrapar una línea de código.Si está utilizando UnityScript, use
import System;
Aquí hay un ejemplo:
También recuerde, se puede tomar también otras excepciones como
MissingReferenceException
,MissingComponentException
,IndexOutOfRangeException
, o cualquier otra clase de excepción, siempre y cuando usted incluyeusing System
en su guión.Eso es todo.
fuente