Jump to content
UnitySpain
Sign in to follow this  
Antonio

Sistema de animaciones, dudas con el planteamiento.

Recommended Posts

Yo me estoy quemando otra vez la cabeza ____by_invader_yuki.gif

Sigo con mi fangame, y me llegó la hora de enfrentarme a las cinemáticas, (cutscenes, eventos, y tal), un par de ellas para el inicio y el final, no muy complicadas ni muy largas. 


- Sé que puedo coger el 3ds max y hacerlas ahí.
- También está la opción de hacerlas en el propio Unity, (le estoy cogiendo truco y todo gracias al sistema de hijos que me permite posar varios modelos a la vez, y lo cierto es que la animación de cámara me es muchísmo más cómodo hacerlo ahí)..

Bueno, como último recurso pues están ahí esas dos opciones para salir del paso, pero la verdad es que, en mis objetivos está:

Requisitos:

  • Poder hacer algo más flexible, que pueda combinar con animaciones ya hechas (tener que animar los pasos del personaje manualmente todo el tiempo sería un tostón... @_@) así, en vez de hacer la super animación de 1 minuto estilo Tomb Raiders antiguos, pues voy haciendo animaciones cortas y las voy activando en su momento por código.
  • Y también está el de poder reutilizar esas animaciones con distintos modelos. En este proyecto, tengo la intención de cambiar el modelo del personaje con distintos trajes como recompensa, de momento va funcionando en la partida pero ahora, pues tengo que ver como adapto el sistema de las cinemáticas para que eso siga funcionando.
  • Uso de animaciones faciales.
  • No son pre-renderizadas ni quiero eso, si no en tiempo real con el motor del juego.


Así que bueno tengo un lío con todo esto que no me aclaro.

A ver, creo que algo así necesitaría:
 

Cámara

- Un objeto vacío (invisible y sin colisión) para ponerle la cámara de cinemáticas, y el animator, y así, usar el sistema gráfico del mecanim para crear los distintos estados con las distintas animaciones de cámara.

- Un código que maneje las cámaras: Esto podría ser un array de tipo personalizado, cada nodo, tendría una variable float, que sería el tiempo en el que se cambiará al siguiente nodo, y en el proceso, le diría a mecanim de la cámara que pase al siguiente estado de animación. En este código también podría hacer cosas como modificar los efectos de las cámaras, el FoV, y cosas de ese estilo.

Animatings

- Cada objeto de la escena, tendrán también su propia animación en mecanim, con una variable de tiempo, algún código se encargará de actualizarla como es debido, usando esta variable, los estados de la animación se sucederán en el momento necesario. Ya dentro de las animaciones propia, les pondría sus eventos para que activen los sonidos que necesiten. Ya tengo un código para los sonidos que puedo reutilizar ahí. También podría crear algunas ordenes sencillas de esas de apuntar a cierto objetivo, o de recrear un pequeño temblor para simular el efecto de una cámara manual.

Personajes

- Necesito el código para inutilizar el comportamiento del jugador y poder añadir su nuevo del animating. ¿alguna idea por aquí O.ò?

- Estos personajes también usan mecanim, así que pueden intercambiar las animaciones corporales, sus gráficos de mecanim, tendrán 3 capas:

  1. La general, que es la que siempre maneja la posición del personaje en el espacio.
  2. La del tronco superior (si está andando, y quiero que esté hablando o moviendo los brazos, con esto podría ahorrarme los pasos, y tal).
  3. La de animaciones faciales. (Que es la que no sé como transferir de un modelo a otro, ¿alguna idea por aquí O.ò ? ).

- Su paso entre animaciones, creo que podría hacerlo también con la variable de tiempo, y así, cada capa podría actualizarse de manera interna. Tendría que distinguir entre las animaciones que son cíclicas durante un tiempo (correr, caminar) y las que son únicas (encender comunicador, apoyarse en una silla), estoy podría hacerlo haciendo que las animaciones  cíclicas dependan del trigger, y las animaciones únicas, al terminar, pasarán a la siguiente animación o a un estado vacío en caso de que no haya, y este será el que espere a la llamada del siguiente disparador.

- Entonces en realidad el código tan sólo tendría que encargarse de actualizar el tiempo en el mecanim, y asegurarse de cortarlo todo cuando acabe. Nop, no puedo, necesito añadir más cosas a parte de la animación, la rotación, o el punto de destino, podría hacerlo como un PNJ con IA, para que se pueda mover por el escenario, en algunos momentos, algo parecido a las escenas de los RPGs antiguos, que los pnjs se van a una posición donde realizan alguna animación, puede que a veces tenga que moverlos mediante el root motion, otras veces puede que tenga que trasladarlos a la fuerza, pero creo que valdría la pena dejar esas funciones implementadas.

869682-1_16_2009_10_52_46_am.png

Efectos

- Aquí imagino que iré de nuevo a algo como el código del array que usé en las cámaras, ya que el caso de los subtítulos, tal y como lo tengo, he de acceder a distintos archivos dependiendo del idioma, es algo que tendría que mirar por código, no creo que pueda automatizarlo con una animación de datos.

- El asunto de la música, aun tengo que programar todo eso @_@, pero imagino que necesitaré un par de listas, una para la música y otro para los efectos de sonido que no vayan a ir en las animaciones si es que pongo alguno. O_ò, no creo que tenga voces.

 

 

Bueno, visto ahora, no parece tan imposible, aunque sigo con la incógnita del manejo de animaciones faciales entre distintos modelos. Mecanim, por lo que sé, sólo guarda la animación de los ojos y la mandíbula. Necesitaría los labios, las cejas y los párpados. 

Se me ocurre, que quizás, podría crear un objeto vacío, que esté a la altura del cuello y con su animator, como hijo de este objeto vacío pues podría crear más hijos invisibles (para cada uno de esos huesos significativos), a la hora de hacer la animación facial, estos huesos vacíos, son los que se moverían, y son los que guardarían la animación, así que esta cara ficticia, sería un prefab, algo como una máscara. Cuando el personaje, entre en modo cinemática, se instanciaría esa máscara, y se enlazarían los huesos del personaje, (los que existan) con los huesos de la máscara. para esto podría ayudarme algún pequeño código en el personaje que tenga los huesos ya guardados manualmente, habría que configurarlo para cada modelo, pero sería información que se podría guardar en su prefab así que creo que podría ser factible.

 

Vale, creo que de momento con esto tengo algunas pasos que seguir, (imagino que habrá que empezarlo en algún momento) pero aún así si alguien tiene ideas u otros enfoques para el tema que puedan facilitar el asunto, serían bienvenidas, 

Share this post


Link to post
Share on other sites

En principio, el tema de las cinemáticas y la configuración del personaje(ropa, accesorios, etc...) no debería plantear problemas, porque el proceso consiste en Animator-->SkinnedMeshRenderer-->Malla, y lo que se hace es compartir un mismo SkinnedMeshRenderer entre todas las mallas del personaje.

 

Respecto a las cinemática, las que he hecho han sido mezclando animaciones 3D(hechas en un modelador: caminar, hablar) con animaciones de Unity(Eventos de animacion para activar animaciones 3D y sonidos, y mover o rotar el personaje directamente). Es decir, desde un GameObject con un componente Animation o Animator activas la animacion de Unity con el proceso de cinemática que modificaría el componente Animator de los personajes para caminar, hablar etc... y ejecutaría sonidos o efectos de partículas.

Edited by kaito

Share this post


Link to post
Share on other sites

Bueno, ya tengo lo básico hecho, al final con el gráfico del mecanim pues la cosa ha resultado más sencilla de lo que esperaba, pero aún tengo que ver como pasar el bache de las animaciones faciales.

De momento, 
en el código simplemente he tenido que:

1º Manejar un poco el bloqueo de controles del jugador  (los allowInput puestos en false) y ponerlo en un estado de "operativo" false para que los enemigos dejen de ir a por él. También he tenido que resetear el sistema de apuntado porque afectaba a la cámara si activaba la escena mientras apuntaba. Y he tenido que reemplazar su animator Controller por el animator controller que tenía la información de la cinemática (guardando el que tenía para volver a ponérselo cuando termine). También le he puesto un array de Transforms para llenarlo con posiciones del escenario que me hagan falta, y un índice para pasear por dicho array.

2º  En el animator controller de la cinemática, he puesto una serie de animaciones seguidas, la propia interfaz permite poner que las siguientes animacionse se activen tras X tiempo, (por ejemplo, pongo la de correr y puedo decirle que empiece la de frenado tras los 5 segundos), pero igualmente, he puesto la variable timer que lleva el progreso de toda la cinemática, (si tengo una canción de fondo, y sé que en el segundo 38 sale un estribillo, pues puedo usar esa variable directamente para activar la nueva animación, en vez de ponerme a sumar los segundos de todas las animaciones anteriores).  En dicho controller, también he puesto tags a algunos estados:

Look_At - Hace que el personaje miré a la posición que hay en el array indicado por el índice.

Next_Target - Aumenta el índice 1 valor.

End - Lo pongo en el estado final, para que este personaje recupere su comportamiento de jugador normal.

Para estos tags, también he creado la función con la que poder llamarla por medio de eventos, (los tags parece que van bien y son cómodos, pero cubren toda la animación de ese estado, si quiero que sólo se gire durante una parte de la animación, creo que los eventos que dice Kaito son una manera más centrada).

3º El manejo de que la animación no se repita o reactive, lo llevo directamente con los triggers, asi que aqui no meto nada de eso.

4º El manejo de las distintas capas, también lo hago poniendo la secuencia directamente en el esquema del animator, (Diciendo en que segundo se tiene que activar cada animación, y poniendo un estado vacío cuando sólo quiero se ejecute la animación de la capa base.

using UnityEngine;
using System.Collections;

public class Seq_Player : MonoBehaviour 
{
	float CurTempo;
	float StartTime;
	bool ActiveFlag = false;
	Player_Input PI;
	Player_Controller PC;
	Player_Stats PS;
	Animator Anim;
	public RuntimeAnimatorController  Cutscene;
	RuntimeAnimatorController Previous;

	public Transform[] SpaceTargets;
	int CurIndex = 0;
    bool ScriptMov = false;

	// Use this for initialization
	void Start () 
	{
		PI = GameObject.FindGameObjectWithTag ("Player").GetComponent<Player_Input> ();
		PC = GameObject.FindGameObjectWithTag ("Player").GetComponent<Player_Controller> ();
		PS = GameObject.FindGameObjectWithTag ("Player").GetComponent<Player_Stats> ();
		Anim = GameObject.FindGameObjectWithTag ("Player").GetComponent<Animator> ();
	}

	void InicSeq ()
	{
		PI.AllowInput = false;
		PI.AllowInput = false;
		PI.AllowAnimatorRefresh = false;
		PI.aim = false;
		PI.lookInCameraDirection = false; //Because this would need another cycle to reset after the aim, so we reset it manually.
		PS.libre = false;
		PS.Operative = false;

		Previous = Anim.runtimeAnimatorController;
		Anim.runtimeAnimatorController = Cutscene;

		StartTime = Time.time;
		CurIndex = 0;

		ActiveFlag = true;
	}

	void StopSeq ()
	{
		Anim.runtimeAnimatorController = Previous;

		PI.AllowInput = true;
		PI.AllowInput = true;
		PI.AllowAnimatorRefresh = true;
		PS.libre = true;
		PS.Operative = true;
		ActiveFlag = false;
	}

    void EventAction (int value)
    {
        switch (value)
        {
            case 0: 
                ScriptMov = false;
                break;
            case 1: 
                ScriptMov = true;
                break;
            case 2: 
                CurIndex ++;
                break;
            case 3: 
                StopSeq ();
                break;
        }
    }
		
	void Update () 
	{
		if (ActiveFlag) 
		{
			CurTempo = Time.time - StartTime;
			Anim.SetFloat ("Timer", CurTempo);

			if ((Anim.GetCurrentAnimatorStateInfo (0).IsTag ("Look_At"))  || (ScriptMov))
			{
				if (CurIndex < SpaceTargets.Length) 
				{
					PC.Move (Vector3.zero,false,SpaceTargets[CurIndex].position);
                    //Hace que la entidad se mueva o gire en este caso, hacia la posición indicada, su contenido está en otro código.
				}
			}

			if (Anim.GetCurrentAnimatorStateInfo (0).IsTag ("Next_Target")) 
			{
				CurIndex++;
			}

			if (Anim.GetCurrentAnimatorStateInfo (0).IsTag ("End")) 
			{
				StopSeq ();
			}
		}
		
	}

	void DoActivateTrigger ()
	{
		InicSeq ();
	}
}


Me queda lo de las animaciones faciales en Mecanim, pero de hecho estoy teniendo problemas con las animaciones ya en sí. (Tengo hechas varias poses faciales, pero aunque durante el gameplay van bien, durante la secuencia veo que sólo me funcionan 3 de las 5, no sé que le pasa a las otras dos ).

 

No termino de entender muy bien lo del Skinned Mesh Renderer , ahora mismo, cada "mesh" tiene ese componente,

Mi personaje está montado en un objeto vacío con el animator y todos los códigos, y luego, como hijo tiene el modelo, el animator coge el avatar de este, y fin, por lo que mi cambiar traje ahora mismo es:
- Desvincular armas de los huesos
- Cambiar el modelo, instanciándolo por ejemplo,
- Actualizar el animator
- Re-vincular armas a los huesos del nuevo modelo.

Si pusiera que todos los modelos se controlaran por un sólo Skinned Mesh Renderer, ¿No habría conflicto si cada modelo trajese algunas diferencias en el esqueleto? Al ser el mismo personaje de momento, sus huesos faciales son los mismos, algunos trajes tienen huesos extras en la camisa, o el abrigo, o tal, pero pensando en que algún día en vez de un traje nuevo podría ser un personaje diferente, este tendría una estructura distinta (a lo mejor 4 huesos labiales en vez de 8 y tal). ¿El Skinned Mesh Renderer lo llevará bien?

 

 

Share this post


Link to post
Share on other sites
Sign in to follow this  

×
×
  • Create New...