Animation
GUI Anterior

Scripting de Animación (Legacy)

El sistema de Animación de Unity le permite crear unas hermosas animaciones de personajes con Skinning. El Sistema de Animación soporta la fusión de animaciones (animation blending), mixing (mezcla), animaciones aditivas, sincronización walk cycle time, capas de animación, control sobre todos los aspectos de la reproducción de la animación (tiempo, velocidad, pesos de blending), mesh skinning con 1, 2, o 4 huesos por vertex (vértice) al igual que el soporte de rag-dolls basados en físicas y animaciones procedimentales. Para obtener el mejor resultado, se recomienda que usted lea acerca de las mejores prácticas y técnicas para crear un personajes rigged con un rendimiento optimo en Unity en la página Modelando Personajes Optimizados.

Crear un personaje animado implica dos cosas; Moverlo a través del mundo y animarlo como corresponde. Si quiere aprender más sobre cómo mover los personajes alrededor, mire la página del Character Controller. Esta página se enfoca en la animación. La animación real de los personajes se realiza a través de la interfaz de scripting de Unity.

Puede descargar los demos de ejemplo que muestran personajes con animaciones pre-configuradas. Una vez haya aprendido lo básico en esta pagina también podrá ver la interfaz de script de animación.

Animation Blending (Fusión de animaciones)

En los juegos modernos, la fusión de animaciones es una característica esencial para asegurar que los personajes tengan animaciones fluidas. Los animadores crean las animaciones por separado, por ejemplo, un walk cycle (ciclo para caminar), un ciclo para correr, una animación de inactividad o de disparo. En cualquier instante durante la ejecución de su juego usted debe ser capaz de realizar una transición desde la animación de inactividad hacia el walk cycle y viceversa. Naturalmente, la transición debe ser fluida y evitar saltos repentinos en el movimiento.

Aquí es donde la animation blending (fusión de animaciones) entra. En Unity usted puede tener cualquier número de animaciones reproduciéndose en el mismo personaje. Todas las animaciones se fusionan o se añaden juntas para generar la animación final.

Nuestro primer paso será hacer que un personaje se blend (fusione) suavemente entre el estado inactivo y las animaciones para caminar. Con el propósito de hacer el trabajo del programador más fácil, primero vamos a establecer el Wrap Mode de la animación a Loop. Luego vamos a quitar Play Automatically para estar seguros que nuestro script sea la única animación reproduciéndose.

Nuestro primer script para animar el personaje es muy simple; sólo necesitamos una manera de detectar qué tan rápido nuestro personaje se mueve, y luego cambiar entre las animaciones para caminar e inactivo de manera sútil. Para esta simple prueba, vamos a usar los ejes de entrada estándar:-

function Update () {
   if (Input.GetAxis("Vertical") > 0.2)
       animation.CrossFade ("walk");
   else
      animation.CrossFade ("idle");
}

Para utilizar este script en su proyecto:-

  1. Cree un archivo Javascript utilizando Assets > Create > Javascript.
  2. Copie y pegue el código a él
  3. Arrastre el script hacia el personaje (necesita estar adjunto al GameObject que tenga la animación)

Cuando oprima el botón de Play (reproducción), el personaje empezará a caminar en su lugar mientras usted presione la flecha (tecla) hacia arriba y volverá a una posición en espera cuando libere el botón.

Capas de Animación

Las capas son un concepto realmente útil que le permite agrupar animaciones y dar prioridad a la ponderación.

El sistema de animación de Unity puede fusionar tantos clips de animación que usted desee. Usted puede asignar los pesos de blend (fusión) manualmente o simplemente usar animation.CrossFade(), el cual animará el peso automáticamente.

Los pesos de blend (fusión) siempre están normalizados antes de que sean aplicados

Suponga que usted tiene un ciclo para caminar y un ciclo para correr, ambos con un peso/ponderación de 1 (100%). Cuando Unity generé la animación final, normalizará los pesos/ponderación, lo cual significa que el ciclo para caminata contribuirá 50% a la animación y el ciclo para correr también contribuirá 50%.

Sin embargo, usted generalmente querrá priorizar cuál animación recibe mayor peso cuando hay dos animaciones en reproducción. Es posible asegurarse, de manera manual, que la suma de los pesos sea de 100%, pero es más fácil simplemente usar capas para lograrlo.

Ejemplo del uso de capas

Como un ejemplo, usted puede tener una animación para disparar, una para estar inactivo y una para un ciclo caminando. Las animaciones para caminar e inactividad serán blended (fusionadas) basándose en la velocidad del jugador pero cuando el jugador dispare, usted querrá mostrar sólo la animación de disparo. En consecuencia, la animación de disparo tendrá esencialmente una prioridad más alta.

La manera más sencilla de hacer esto es simplemente seguir reproduciendo las animaciones para caminar y estar inactivo mientras dispare. Para hacer esto, se necesita estar seguros de que la animación de disparo está en una capa superior que la animación para caminar y de estar inactivo, lo que significa que la animación de disparo recibirá el blend weight (peso de fusión) primero. La animación para caminar y de estar inactivo recibirá peso solo si la animación de disparo no usa el 100% de la ponderación del blend (fusión). Entonces cuando realice un CrossFading a la animación de disparo, el peso comenzará en cero y durante un período corto se volverá 100%. Al principio las capas walk (caminar) y idle (sin actividad) van a recibir blend weights (pesos de fusión) pero cuando la animación de disparo entra completamente, estas no recibirán pesos en absoluto. Esto es lo que exactamente se necesita.

function Start () {
   // Set all animations to loop
   animation.wrapMode = WrapMode.Loop;
   // except shooting
   animation["shoot"].wrapMode = WrapMode.Once;

   // Put idle and walk into lower layers (The default layer is always 0)
   // This will do two things
   // - Since shoot and idle/walk are in different layers they will not affect
   // each other's playback when calling CrossFade.
   // - Since shoot is in a higher layer, the animation will replace idle/walk
   // animations when faded in.
   animation["shoot"].layer = 1;

   // Stop animations that are already playing
   //(In case user forgot to disable play automatically)
   animation.Stop();
}

function Update () {
   // Based on the key that is pressed,
   // play the walk animation or the idle animation
   if (Mathf.Abs(Input.GetAxis("Vertical")) > 0.1)
      animation.CrossFade("walk");
   else
      animation.CrossFade("idle");

   // Shoot
   if (Input.GetButtonDown ("Fire1"))
      animation.CrossFade("shoot");
}

Por defecto animation.Play() y animation.CrossFade() detendrán o desvanecerán las animaciones en la misma capa. Esto es exactamente lo que queremos en la mayoría de los casos. En nuestro ejemplo de disparo, inactivo y corriendo, reproducir la de estar inactivo y corriendo no afectará la animación de disparo ni viceversa (puedes cambiar el comportamiento con un parámetro para animation.CossFade opcional si lo deseas).

Animation Mixing (Mezcla de animaciones)

La animation mixing le permite cortar el número de animaciones que necesita crear para su juego teniendo algunas animaciones aplicadas solamente a una parte del cuerpo. Esto significa que esas animaciones se pueden utilizado en conjunto con otras animaciones en varias combinaciones.

Usted agrega un transform de la animation mixing a una animación llamando AddMixingTransform() en el dado AnimationState (estado de animación).

Ejemplo de mixing

Un ejemplo de mixing puede ser algo como una animación que saluda con la mano. Puede que quiera que salude con la mano tanto cuando el personaje está inactivo o cuando está caminando. Sin la mezcla de animación (animation mixing) usted tendría que crear animaciones separadas para los saludos en el estado inactivo y caminando. Sin embargo, si añade el transform de hombro como un transform de mezcla (mixing) a la animación que saluda con la mano, esta animación tendrá el control completo solo de la articulación del hombro a la mano. Dado que el resto del cuerpo no será afectado por el saludar con la mano, este continuará reproduciendo la animación de inactivo o de caminar. Consecuentemente, solo la animación única es necesaria para hacer el saludo con la mano mientras el resto del cuerpo usa la animación de inactivo o de caminar.

/// Adds a mixing transform using a Transform variable
var shoulder : Transform;
animation["wave_hand"].AddMixingTransform(shoulder);

Otro ejemplo es usando una ruta.

function Start () {
   // Adds a mixing transform using a path instead
   var mixTransform : Transform = transform.Find("root/upper_body/left_shoulder");
   animation["wave_hand"].AddMixingTransform(mixTransform);
}

Additive Animations (Animaciones aditivas)

Las animaciones aditivas y el mixing de animaciones le permite a usted cortar el número de animaciones que tiene que crear para su juego, y son importantes para crear animaciones faciales.

Suponga que usted quiere crear un personaje que se incline a los lados a medida que gira mientra camina y corre. Esto lleva a cuatro combinaciones (caminar-inclinarse-izquierda, caminar-inclinarse-derecha, correr-inclinarse-izquierda, correr-inclinarse-derecha), cada uno el cual necesita una animación. Creando una animación por separada para cada combinación claramente lleva a trabajo extra incluso en este simple caso, pero el número de combinaciones aumenta dramáticamente con cada acción individual. Por fortuna, una animación aditiva y mezclada evita la necesidad de producir animaciones por separado para las cominaciones de movimientos simples.

Ejemplo de Additive Animation (Animación aditiva)

Las animaciones Aditivas le permite a usted sobreponer los efectos de una animación encima de cualquiera otra que se esté reproduciendo. Cuando se esté generando animaciones aditivas, Unity va a calcular la diferencia entre el primer cuadro en el clip de animación y el cuadro actual. Luego va a aplicar esta diferencia encima de todas las otras animaciones reproduciéndose.

Refiriéndose al ejemplo anterior, usted puede hacer que las animaciones se inclinen a la derecha e izquierda y Unity podría ser capaz de sobreponer estas en el ciclo caminado, sin actividad o corriendo. Esto se puede lograr con código como el siguiente:-

private var leanLeft : AnimationState;
private var leanRight : AnimationState;

function Start () {
   leanLeft = animation["leanLeft"];
   leanRight = animation["leanRight"];

   // Put the leaning animation in a separate layer
   // So that other calls to CrossFade won't affect it.
   leanLeft.layer = 10;
   leanRight.layer = 10;

   // Set the lean animation to be additive
   leanLeft.blendMode = AnimationBlendMode.Additive;
   leanRight.blendMode = AnimationBlendMode.Additive;

   // Set the lean animation ClampForever
   // With ClampForever animations will not stop 
   // automatically when reaching the end of the clip
   leanLeft.wrapMode = WrapMode.ClampForever;
   leanRight.wrapMode = WrapMode.ClampForever;

   // Enable the animation and fade it in completely
   // We don't use animation.Play here because we manually adjust the time
   // in the Update function.
   // Instead we just enable the animation and set it to full weight
   leanRight.enabled = true;
   leanLeft.enabled = true;
   leanRight.weight = 1.0;
   leanLeft.weight = 1.0;

   // For testing just play "walk" animation and loop it
   animation["walk"].wrapMode = WrapMode.Loop;
   animation.Play("walk");
}

// Every frame just set the normalized time
// based on how much lean we want to apply
function Update () {
   var lean = Input.GetAxis("Horizontal");
   // normalizedTime is 0 at the first frame and 1 at the last frame in the clip
   leanLeft.normalizedTime = -lean;
   leanRight.normalizedTime = lean;
}

Recomendación: Cuando utilice animaciones aditivas, es crítico que usted también reproduzca otra animación no-aditiva en cada transform que también es utilizado en la animación aditiva, de lo contrario, las animaciones se agregarían encima del último resultado del cuadro. Esto lo más seguro no es que usted quiere.

Animando personajes procedimentalente

Algunas veces usted quiere animar los huesos de personaje de manera procedimental. Por ejemplo, usted podría querer que la cabeza de su personaje mire un punto en específico en el espacio 3D el cual es mejor manejado por un script que sigue el objeto destino. Afortunadamente, Unity hace esto muy fácil, ya que los huesos son solo Transform que manejan el skinned mesh. Por lo tanto, usted puede controlar los huesos de un personaje desde un script como los Transform de un GameObject.

Una cosa importante para saber es que el sistema de animación actualiza los Transform después de la función Update() y antes de la función LateUpdate(). Por lo tanto si usted quiere hacer una función LookAt() usted debería hacer eso en LateUpdate() para asegurarse que usted de verdad está anulando la animación.

Los Ragdolls son creados de la misma manera. Usted simplemente tiene que adjuntar los Rigidbodies, Character Joints (Articulaciones del personaje y Capsule Colliders a diferentes huesos. Esto luego va a animar físicamente su personaje skinned.

Reproducción de Animación y Toma de Muestras (Sampling)

Esta sección explica cómo las animaciones en Unity se le toma muestras cuando son reproducidas por el motor.

Los AnimationClips típicamente tienen una autoría en una velocidad de cuadro fija. Por ejemplo, usted podría crear su animación en 3ds Max o Maya en una velocidad de cuadros de 60 cuadros por segundo (fps). Cuando importe una animación a Unity, esta velocidad de cuadros será leída por el importador, entonces la información de la animación importada también es muestreada en 60 fps.

No obstante, los juegos típicamente corren en una velocidad de cuadros variable. La velocidad de cuadros puede ser mayor en algunos computadores a otros, y también puede variar de un segundo al siguiente basándose en la complejidad de la vista de la cámara que está viendo en cualquier momento dado. Básicamente esto significa que nosotros podemos no hacer suposiciones acerca de la velocidad de cuadro exacta en la que el juego está corriendo. Lo que esto significa es si una animación tiene autoría en 60 fps, ésta puede ser reproducida en diferentes velocidades de cuadro, como 56.72 fps, 83.14 fps, o prácticamente cualquier otro valor.

Como un resultado, Unity debe tomar muestras de una animación en varias velocidades de cuadro, y no puede garantizar la velocidad de cuadro para la cual originalmente fue diseñada. Por fortuna, las animaciones para los gráficos de computador 3D no consisten de cuadros discretos, pero más bien curvas continuas. Estas curvas pueden ser muestradas en cualquier punto en el tiempo, no solamente en esos puntos de tiempo que corresponden a los cuadros en la animación original. De hecho, si el juego corre a una velocidad de cuadro mayor a la que la animación fue creada, la animación en realidad se vería más suave con un mejor flujo en el juego a la animación en el software de animación.

Para unas razones muy prácticas, usted puede ignorar el hecho de que Unity toma muestras de animaciones en varias velocidades de cuadro. Sin embargo, si usted tiene una lógica de juego que dependen en animaciones que animan los transforms o propiedades a una configuraciones en especifico, entonces usted necesita tener en cuenta el re-muestreo que toma lugar detrás de escenas. Por ejemplo, si usted tiene una animación que gira un objeto de 0 a 180 grados en 30 cuadros, y quiere saber desde su código cuándo ha llegado a la mitad del camino, usted no debería hacerlo teniendo declaraciones condicionales en su código que revise si la rotación actual es 90 grados. Ya que Unity muestrea la animación de acuerdo a la velocidad de cuadro variable del juego, lo puede muestrear cuando la rotación es justo debajo de 90 grados, y la siguiente vez cuando ha alcanzado 90 grados. Si usted necesita ser notificado cuando un punto especifico en la animación ha sido alcanzada, usted debería utilizar un AnimationEvent más bien.

Tenga en cuenta que como consecuencia del muestreo de la velocidad de cuadro variable, una animación que es reproducida utilizando WrapMode.Once puede no ser muestrada en el tiempo exacto del último cuadro. En un cuadro del juego, la animación puede ser muestreada justo antes del final de la animación, y en el siguiente cuadro el tiempo puede haberse excedido la duración de su animación, por lo que es desactivada y no es muestre más. Si usted absolutamente necesita tener el último cuadro de la animación en ser muestreada exactamente, usted debería utilizar WrapMode.ClampForever que va a seguir muestreando el último cuadro de manera indefinida hasta que pare la animación usted mismo.

Animation
GUI Anterior