Comunidad orientada al desarrollo de videojuegos

Steering behaviors–Wander

En este post vamos a conocer que son los Steering Behaviors, y vamos a implementar el comportamiento Wander, en C# para utilizarlo en Unity3D.

¿Qué es Steering Behaviors?

Steering Behaviors es el nombre que reciben una serie de procedimientos para animar personajes del juego y darles la posibilidad de moverse de una forma real e improvisada. La definición e implementación de todos estos comportamientos es obra de Craig Reynolds. Los comportamientos son:

  • Buscar y huir (Seek and Flee)
  • Perseguir y evadir (Pursue and Evade)
  • Deambular (Wander)
  • Llegada (Arrival)
  • Evasión de obstáculos (Obstacle avoidance)
  • Seguimiento de pared (Wall following)
  • Seguimiento de camino (Path following)
  • Seguimiento de campos (Flow Filed following)

Todos estos comportamientos se pueden combinar para conseguir comportamientos más realistas y sofisticados. En la web de Craig Reynolds hay una aplicación en la que se combinan muchas de ellas, y es muy recomendable verla en funcionamiento.

Wander

Este comportamiento permite hacer deambular a un personaje de nuestro juego de una forma más o menos realista. Conseguimos que no tenga un desplazamiento lineal, como si siguiera una línea trazada con una regla a lo largo del suelo, pero a la vez, conseguimos que no haga unos cambios de dirección demasiado bruscos.

Para implementar este comportamiento vamos a colocar un círculo delante del personaje, utilizaremos este círculo para calcular las fuerzas involucradas en este desplazamiento.

descripcion

El desplazamiento es una fuerza cuyo origen es el centro del círculo y está limitado por el radio del mismo. Jugando con estas dos variables (el radio y la posición del centro) podemos conseguir comportamientos más o menos suaves. En nuestra implementación estas dos variables serán parámetros del comportamiento.

Posición del círculo

Para colocar el círculo utilizaremos la posición del personaje, concretamente la dirección en la que está mirando. Como hemos dicho anteriormente, la distancia del círculo vamos a dejar que sea modificable, y así poder ajustar la posición del mismo hasta que obtengamos el comportamiento deseado.

posicionCirculo

Para calcular la posición del círculo en un script de C# deUnity3D:

   1: //Obtenemos el vector unitario de la dirección en la que se está moviendo

   2: //y colocamos la distancia indicada por CircleCentre, que es un miembro público

   3: //para poderlo modificar para varios elementos

   4:

   5: Vector3 circleCenter;

   6:

   7: circleCenter = new Vector3(_myTransform.forward.x,_myTransform.forward.y,_myTransform.forward.z);

   8: circleCenter.Normalize();

   9: circleCenter *= CircleDistance;

Fuerza de desplazamiento

Es un vector aleatorio que nace del centro del círculo y con una magnitud R (el radio del círculo). La aleatoriedad viene dada por el ángulo que se le aplica al vector, es un valor que cada frame se recalcula teniendo en cuenta el valor anterior para evitar cambios demasiados bruscos.

desplazamientoFuerza

El script para hacer este cálculo:

   1: //cambiamos en cada frame el ángulo para crear la nueva fuerza y mover al personaje

   2: displacement = new Vector3(0,0,1);

   3: displacement*= CircleRadius;

   4:

   5: _wanderAngle += (Random.value * ANGLE_CHANGE) - (ANGLE_CHANGE * 0.5f);

   6:

   7: SetAngle(ref displacement,_wanderAngle);

La función SetAngle aplica el ángulo al vector que habíamos creado:

   1: void SetAngle(ref Vector3 vector,float angle){

   2:     float len = vector.magnitude;

   3:     vector.x = Mathf.Cos (angle) * len;

   4:     vector.z = Mathf.Sin (angle) * len;

   5: }

Fuerza para “andar”

Una vez que hemos calculado la fuerza de desplazamiento, la fuerza que va a hacer que nuestro personaje se desplace es el vector que hay entre él y el desplazamiento.

andarFuerza

En esta imagen podemos ver como nos puede afectar la distancia del centro y el radio del círculo. Cuanto más cerca esté el círculo del personaje o más grande sea, éste tendrá un movimiento más zigzagueante, mientras que cuanto más lejos y más pequeño, el personaje seguirá una ruta más lineal.

Ya nos quedan los dos últimos pasos para terminar el comportamiento.

Aplicar la fuerza

Después de todos los cálculos que hemos hecho, tenemos que hacer que la fuerza acompañe al personaje. Así se moverá, para ello no hay más que añadir la fuerza al vector que apunta hacia delante, y al vector resultante truncarle con la velocidad máxima del personaje.

   1: Vector3 moveVector = (_myTransform.forward * Speed) + (wanderForce);

   2: moveVector.Normalize();

   3: moveVector *= Speed;

Esta es la posición de destino de nuestro personaje para este frame. Ahora rotamos al personaje para que mire hacia ese punto y lo desplazamos.

   1: _myTransform.rotation = Quaternion.Slerp (_myTransform.rotation, Quaternion.LookRotation (moveVector), RotationSpeed * Time.deltaTime);

   2: _myTransform.position += moveVector * Time.deltaTime;

Y así es como conseguimos que un personaje deambule de forma distraída por una escena.

NOTA: en algunos code-snippets se ve la variable _myTransform, esta no es más que un cacheo de la variable transform del GameObject en el que estamos. La asignación es esta

   1: Transform _myTransform;

   2: void Start () {

   3:     _myTransform = transform;

   4: }

, , ,

Leave a Reply