La mejor forma de dar vida a un enemigo en Unity 2D es con una IA simple de movimiento aleatorio. Aquí verás cómo estructurar un EnemyController en C#, conectar Rigidbody2D y Animator, y controlar tiempos de paso con precisión. Todo está preparado para reutilizarlo en distintos tipos de enemigos sin cambiar el script, solo los gráficos.
¿Cómo crear e integrar el enemy controller?
Para empezar, se crea un script de C# llamado EnemyController y se arrastra al objeto enemigo en la jerarquía. Aunque se llame controller, no lo controlará el jugador: gobierna el movimiento autónomo del enemigo.
¿Qué requisitos debe tener el enemigo?
Tag "enemy" aplicada al objeto enemigo.
Sistema de animaciones con blend tree y parámetros "horizontal" y "vertical".
Collider configurado.
Rigidbody2D agregado.
¿Cómo resolver errores del editor?
Si Visual Studio marca todo en rojo sin motivo: guardar, cerrar y reabrir el script desde Unity.
¿Qué variables controlan la IA y el movimiento aleatorio?
La lógica se basa en dos temporizadores: tiempo entre pasos y tiempo de cada paso. Además, se registra si el enemigo está en movimiento y en qué dirección debe desplazarse. Se comunican los ejes al animator mediante constantes.
usingUnityEngine;publicclassEnemyController:MonoBehaviour{publicfloat enemySpeed =1f;// Velocidad del enemigo.privateRigidbody2D enemyRigidBody;// Referencia al Rigidbody2D.privatebool isMoving;// Estado de movimiento.publicfloat timeBetweenSteps =2f;// Tiempo en reposo entre pasos.privatefloat timeBetweenStepsCounter;// Contador interno de reposo.publicfloat timeToMakeStep =1.5f;// Duración de cada paso.privatefloat timeToMakeStepCounter;// Contador interno de paso.publicVector2 directionToMakeStep;// Dirección del movimiento.privateAnimator enemyAnimator;// Referencia al Animator.privateconststring Horizontal ="horizontal";// Parámetro del blend tree.privateconststring Vertical ="vertical";// Parámetro del blend tree.voidStart(){ enemyRigidBody =GetComponent<Rigidbody2D>(); enemyAnimator =GetComponent<Animator>();// Inicialización de contadores con los valores públicos. timeBetweenStepsCounter = timeBetweenSteps; timeToMakeStepCounter = timeToMakeStep;}
enemySpeed: controla la rapidez del desplazamiento.
isMoving: indica si se está moviendo o está quieto.
timeBetweenSteps/timeBetweenStepsCounter: reposo y su contador interno.
timeToMakeStep/timeToMakeStepCounter: duración del paso y su contador interno.
directionToMakeStep: vector de dirección aleatoria.
enemyRigidBody y enemyAnimator: componentes para movimiento y animación.
"horizontal" y "vertical": nombres exactos de los parámetros del animator.
¿Cómo se programa la lógica en update para moverse y parar?
La mecánica alterna entre reposo y movimiento. En movimiento, se consume el contador del paso y se aplica velocidad en la dirección elegida. En reposo, se espera hasta agotar el contador y se decide una nueva dirección aleatoria.
voidUpdate(){if(isMoving){// Mientras se mueve. timeToMakeStepCounter -= Time.deltaTime; enemyRigidBody.velocity = directionToMakeStep * enemySpeed;if(timeToMakeStepCounter <0f){// Fin del paso: parar y preparar reposo. isMoving =false; timeBetweenStepsCounter = timeBetweenSteps;// Ojo con asignar el correcto. enemyRigidBody.velocity = Vector2.zero;}}else{// Mientras está quieto. timeBetweenStepsCounter -= Time.deltaTime;if(timeBetweenStepsCounter <0f){// Toca iniciar un nuevo paso. isMoving =true; timeToMakeStepCounter = timeToMakeStep;// Dirección aleatoria en X e Y entre -1 y 1. directionToMakeStep =newVector2( Random.Range(-1f,1f), Random.Range(-1f,1f));}}// Notificar la dirección al Animator para el blend tree. enemyAnimator.SetFloat(Horizontal, directionToMakeStep.x); enemyAnimator.SetFloat(Vertical, directionToMakeStep.y);}}
¿Qué ocurre mientras se mueve?
Se decrementa el contador del paso con Time.deltaTime.
Se aplica velocity al rigidbody según la dirección y la velocidad.
Al agotar el tiempo del paso: se detiene, se pone Vector2.zero y se arma el reposo.
¿Qué ocurre mientras está quieto?
Se decrementa el contador de reposo con Time.deltaTime.
Al agotarse: se activa el movimiento, se reinicia el contador del paso y se elige una dirección aleatoria con Random.Range(-1, 1) en X e Y (puede salir diagonal).
¿Cómo sincronizar animaciones con el movimiento?
Se actualizan los parámetros "horizontal" y "vertical" mediante SetFloat.
El blend tree interpreta estos valores para girar la animación según la dirección.
Valores de ejemplo comprobados: enemySpeed = 1. Tiempo entre pasos = 2 s. Tiempo de paso = 1.5 s.
Consejo práctico: hay mucho código dentro de Update; avanza con cuidado para no mezclar contadores.
Próximo paso: crea un prefab con varios enemigos en pantalla y valida el comportamiento.
¿Tienes dudas o ideas para ampliar esta IA? Comparte tu pregunta y cuéntame cómo la adaptarías a tus enemigos.