El anti-patrón#
void Update()
{
// ❌ Buscar por nombre, cada fotograma
GameObject jugador = GameObject.Find("Jugador");
jugador.GetComponent<Salud>().Curar(1);
}Por qué es un problema#
- Rendimiento:
GameObject.Findrecorre todos los objetos de la escena buscando por nombre. Hacerlo enUpdate(60+ veces por segundo) es un desperdicio que escala fatal con escenas grandes. - Frágil: busca por una cadena de texto. Si renombras el objeto ("Jugador" → "Player"), el código deja de funcionar sin ningún aviso del compilador.
- No encuentra objetos desactivados:
Findignora los GameObjects inactivos, fuente de bugs difíciles. - Acoplamiento oculto: la dependencia no se ve en el Inspector; está enterrada en el código.
No exactamente. Una llamada puntual a Find en Start, una sola vez, es perfectamente aceptable en muchos casos. El problema real es llamarlo repetidamente (en Update) o abusar de él como forma habitual de conectar objetos. El matiz importa: no es que Find esté prohibido, es que casi nunca es la mejor herramienta.
Qué hacer en su lugar#
public class Ejemplo : MonoBehaviour
{
// ✅ 1) Referencia asignada en el Inspector: cero búsquedas, visible, rápido
[SerializeField] private Salud saludJugador;
void Update()
{
saludJugador.Curar(1);
}
}Otras alternativas según el caso:
- ¿Es una relación fija entre objetos de la escena? →
[SerializeField]y arrástralo en el Inspector - ¿Necesitas un gestor global único (audio, partida)? → un Singleton o un ScriptableObject de servicio
- ¿Un objeto necesita avisar a otros sin conocerlos? → eventos (
Action/UnityEvent) - ¿Debes encontrar algo dinámico creado en runtime? → guárdalo cuando lo instancias, no lo busques después
- ¿De verdad es una búsqueda puntual e inevitable? →
Finduna vez enStart, y cachea el resultado
Comparativa de coste#
En un proyecto profesional#
En producción casi no verás GameObject.Find. Las dependencias se inyectan (se asignan explícitamente por Inspector, por un instalador de dependencias, o por un localizador de servicios) para que sean visibles, testeables y rápidas. La regla no escrita: si tu código busca objetos por nombre para funcionar, es señal de que falta arquitectura.
Resumen#
GameObject.Find no está prohibido, pero rara vez es la respuesta correcta: es lento en bucle, frágil ante renombrados y esconde dependencias. Prefiere referencias [SerializeField], eventos o servicios. Guarda Find para búsquedas puntuales inevitables, siempre cacheando el resultado.