El mensaje#
MissingReferenceException: The object of type 'GameObject' has been destroyed
but you are still trying to access it.
Torreta.Disparar () (at Assets/Scripts/Torreta.cs:34)Qué significa#
Estás usando un objeto de Unity (un GameObject o componente) que fue destruido con Destroy, pero tu script todavía guarda una referencia a él e intenta usarlo. El objeto "ya no está", pero tu variable sigue apuntando a su fantasma.
MissingReference vs NullReference#
Se confunden, pero son distintos:
| NullReferenceException | MissingReferenceException | |
|---|---|---|
| Causa | La variable nunca apuntó a nada (null) | La variable apuntaba a algo que fue destruido |
| Ejemplo típico | Referencia del Inspector sin asignar | Guardaste un objetivo y le hiciste Destroy |
| Pista | "object reference not set" | "has been destroyed but you are still trying to access it" |
Ver también NullReferenceException.
Ejemplo que lo provoca#
public class Torreta : MonoBehaviour
{
private GameObject objetivo;
void FijarObjetivo(GameObject o) => objetivo = o;
void Disparar()
{
// Si el objetivo murió (Destroy) y no lo hemos limpiado, esto peta
transform.LookAt(objetivo.transform); // MissingReferenceException
}
}El enemigo objetivo se destruyó, pero objetivo sigue "apuntando" a él.
Cómo prevenirlo#
1. Comprobar con == null (Unity lo entiende)#
Unity sobreescribe el operador == para que un objeto destruido se compare como null:
void Disparar()
{
if (objetivo == null) return; // Unity detecta el objeto destruido
transform.LookAt(objetivo.transform);
}Aunque en C# la referencia técnicamente sigue existiendo, Unity hace que objetoDestruido == null devuelva true. Por eso if (objetivo == null) es la comprobación correcta. Ojo: el operador ?. usa el null puro de C#, así que objetivo?.Hacer() no detecta un objeto destruido de Unity. Con objetos de Unity, prefiere if (x == null) a x?..
2. Limpiar la referencia al destruir#
Cuando destruyas algo, avisa a quien lo usaba (con eventos) o pon la referencia a null.
3. Darse de baja de eventos#
Un caso clásico: un objeto destruido seguía suscrito a un evento. Desuscríbete siempre en OnDisable/OnDestroy (ver eventos).
Cómo localizarlo#
Igual que con NullReference: la última línea del error (Torreta.cs:34) te lleva a la línea exacta. Ahí hay una variable que apunta a un objeto ya destruido. Pregúntate: ¿qué destruí que todavía estoy usando?
Errores frecuentes#
- Guardar una referencia a un enemigo/objeto y seguir usándola tras
Destroy. - Usar
?.esperando que detecte objetos destruidos de Unity (no lo hace). - No darse de baja de eventos y que un objeto muerto siga "escuchando".
- Corrutinas que siguen usando un objeto ya destruido.
Resumen#
MissingReferenceException = usas un objeto de Unity que ya destruiste. Se diferencia del NullReference en que aquí la referencia sí apuntó a algo, pero ese algo murió. Protégete con if (x == null) (que Unity entiende para objetos destruidos, a diferencia de ?.), limpia las referencias al destruir y date de baja de los eventos.