Yes. Totally doable. Here some tests i make with success.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// MOON(S) 20.62 MODULE ANIMATION +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// -n$(Line) "$(File)"
#pragma warning disable 0168 // variable declared but not used.
#pragma warning disable 0414 // is assigned but its value is never used
#pragma warning disable 0642 // Possible mistaken empty statement
using UnityEngine;
using System;
using System.Collections;
public class RobotAnimTEST : MonoBehaviour{
private int myID;
private Transform PiedGauche;
private Transform PiedDroit;
const float CrossFadeTempo = float.NegativeInfinity; // IMPORTANT !!!
protected Animator animRobot;
private Rigidbody rigBody;
private float Speed = 0.0f;
private float Pg = 0.0f;
private float Pd = 0.0f;
private AnimatorStateInfo currentState;
// Animation flags / Var ------------------------------------------------------------------------------
private bool IsArmed = false;
private bool IsWeapon = false;
private bool IsWalk = true;
private bool IsRun = false;
private bool IsCrouch = false;
private bool IsCover = false;
private bool ICanStartMove = true;
private bool ICanStopMove = false;
private bool ICanBlendMove = false;
private bool ImInCrouch = false;
private bool ImInBlend = false;
private bool ImInIdle = false;
private int WeaponLayer = 1;
private float WeaponLayerWeight = 0.0f;
private float GetWeaponTime = 0.0f; // Time to arm the weapon.
private float DropWeaponTime = 0.0f; // Time to drop the weapon.
private float IdlePlayTime = 0.0f;
private float RetardAnimation = 0.0f;
private string AnmName = ""; // Nom Anim
private float AnmDuree = 0.0f; // Duree Anim. Pour le retard d'Invoke
private float AnmSpeed = 0.0f; // Speed du Perso
private float AnmSpeedDelais = 0.0f; // Retard au demarrage du perso. Eviter effet de "glissement"
private float AnmStopDelais = 0.0f; // Retard a l'arret du perso. Eviter effet de "glissement"
// Animation flags ------------------------------------------------------------------------------------
[Header("TWEAK DU TEMPO CROUCH")]
[Range(0.05f,0.08f)] public float TimeCrouchToWalk = 0.05f;
[Range(0.05f,0.08f)] public float TimeCrouchToRun = 0.05f;
[Range(0.02f,0.05f)] public float TimeStandToCrouch = 0.05f;
[Range(0.30f,0.60f)] public float TimeToCrouchIdle = 0.50f;
[Range(0.01f,0.04f)] public float TimeCrouchToStand = 0.03f;
[Range(0.20f,0.30f)] public float TimeToBlend = 0.30f;
// *******************************************************************************
// *******************************************************************************
/*
Nom,Duree,Speed,RetardVitesse,StopVitesse
1 IDLE1,0,0,0,0
2 IDLE2,0,0,0,0
3 IDLE3,0,0,0,0
4 IDLE4,0,0,0,0
5 IDLE5,0,0,0,0
6 IDLE6,0,0,0,0
7 WALK,0,0,0,0
8 RUN,0,0,0,0
9 CROUCH,0,0,0,0
10 WALKSTART,0.767,1,0.1,0
11 RUNSTART,0.767,3.2,0.2,0
12 CROUCHSTART,0.6,1,0,0
13 STOP_WALK_GAUCHE,0,0,0,0.6
14 STOP_WALK_DROIT,0,0,0,0.6
15 STOP_RUN_GAUCHE,0,0,0,0.4
16 STOP_RUN_DROIT,0,0,0,0.4
17 STOP_CROUCH_GAUCHE,0,0,0,0
18 STOP_CROUCH_DROIT,0,0,0,0
19 RIFLE_WALKSTART,0.767,1,0.1,0
20 RIFLE_WALK,0,0,0,0
21 RIFLE_STOP_WALK_GAUCHE,0,0,0,0.6
22 RIFLE_STOP_WALK_DROIT,0,0,0,0.6
23 IDLECROUCH,0,0,0,0
24 GETGUN,0,0,0,0
25 DROPGUN,0,0,0,0
*/
// *******************************************************************************
// *******************************************************************************
// public readonly string[] names = { "alpha", "beta", "gamma", "delta" };
public string[] names = { "alpha", "beta", "gamma", "delta" };
public void NewEvent() // test event d'animation.
{
Debug.Log("EVENT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
void Start (){
myID = GetInstanceID();
animRobot = GetComponent<Animator>();
animRobot.applyRootMotion = false;
//animRobot.cullingMode = AnimatorCullingMode.CullUpdateTransforms; // Retarget, IK and write of Transforms are disabled when renderers are not visible.
//animRobot.cullingMode = AnimatorCullingMode.AlwaysAnimate; // Always animate the entire character. Object is animated even when offscreen.
animRobot.cullingMode = AnimatorCullingMode.CullCompletely; // Animation is completely disabled when renderers are not visible.
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//animRobot.updateMode = AnimatorUpdateMode.Normal; // Normal update of the animator.
animRobot.updateMode = AnimatorUpdateMode.AnimatePhysics; // Updates the animator during the physic loop in order to have the animation system synchronized with the physics engine.
//animRobot.updateMode = AnimatorUpdateMode.UnscaledTime; // Animator updates independently of Time.timeScale.
rigBody = GetComponent<Rigidbody>();
PiedGauche = animRobot.GetBoneTransform(HumanBodyBones.LeftFoot);
PiedDroit = animRobot.GetBoneTransform(HumanBodyBones.RightFoot);
ICanStartMove = true;
ICanStopMove = false;
ICanBlendMove = false;
WeaponLayerWeight = 0.0f; // IMPORTANT ?!
animRobot.SetLayerWeight(WeaponLayer, WeaponLayerWeight);
IdleMove();
}
void Update(){
if (Input.GetKeyDown("m") && ICanStartMove) InitMove();
if (Input.GetKeyDown("m") && ICanBlendMove) InitBlend();
if (Input.GetKeyDown("s") && ICanStopMove) StopMove();
if (Input.GetKeyDown("w")) GetWeapon();
if (Input.GetKeyDown("c")) DropWeapon();
//bool isRunningPressed = Input.GetKey("left shift") && Input.GetKey("w");
IsWalk = true;
IsCrouch = false;
IsRun = false;
if (Input.GetKey(KeyCode.LeftShift)) // Run ++++++++++++++++++++
{
IsWalk = false;
IsCrouch = false;
IsRun = true;
}
if (Input.GetKey(KeyCode.RightShift)) // Crouch ++++++++++++++++
{
IsWalk = false;
IsCrouch = true;
IsRun = false;
}
}
void FixedUpdate(){
if (ImInIdle){
//float playbackTime = animRobot.GetCurrentAnimatorStateInfo(0).normalizedTime; // Entier = le nombre de fois que l'anim a été jouée. Décimal = % de play de l'anim
// NE FONCTIONNE PAS EN CROSFADE !!!!!!!!!!!
//playbackTime = (float)Math.Round((float)playbackTime, 2);
//Debug.Log("playbackTime = " + playbackTime);
//Debug.Log("IsInTransition = " + animRobot.IsInTransition(0)); // ne semble fonctionner que pour le CrossFade !!!
if (Time.time > IdlePlayTime){
IdleMove();
}
} else rigBody.MovePosition(transform.position + transform.forward * Time.fixedDeltaTime * Speed );
//if (!ImInIdle) rigBody.MovePosition(transform.position + transform.forward * Time.fixedDeltaTime * Speed );
// Get Weapon and close Weapon *********************************************************
if (IsWeapon && WeaponLayerWeight < 1.0f){
WeaponLayerWeight += Time.fixedDeltaTime / GetWeaponTime;
animRobot.SetLayerWeight(WeaponLayer, WeaponLayerWeight);
}
if (!IsWeapon && WeaponLayerWeight > 0.0f){
WeaponLayerWeight -= Time.fixedDeltaTime / DropWeaponTime;
animRobot.SetLayerWeight(WeaponLayer, WeaponLayerWeight);
}
// Get Weapon and close Weapon *********************************************************
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// GESTION ANIM ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void InitMove() // ============================================================================
{
ImInIdle = false;
if (IsArmed){
// Anim mode Armed
if (IsWalk){
AnmName = "RIFLE_WALKSTART";
AnmDuree = 0.767f;
AnmSpeed = 1.0f;
AnmSpeedDelais = 0.10f;
}
if (IsRun);
if (IsCrouch);
} else
{
if (IsWalk){
AnmName = "WALKSTART";
AnmDuree = 0.767f;
AnmSpeed = 1.0f;
AnmSpeedDelais = 0.10f;
}
if (IsRun){
AnmName = "RUNSTART";
AnmDuree = 0.767f;
AnmSpeed = 3.2f;
AnmSpeedDelais = 0.2f;
}
if (IsCrouch){
AnmName = "CROUCHSTART";
AnmDuree = 0.600f;
AnmSpeed = 1.0f;
AnmSpeedDelais = 0.0f;
}
}
// Y'a du crouch ici !!!!!!! ******************************
if (ImInCrouch && IsWalk){
ImInCrouch = false;
animRobot.CrossFade( "WALK", TimeCrouchToWalk, -1, CrossFadeTempo);
Invoke("InitSpeed", AnmSpeedDelais);
} else if (ImInCrouch && IsRun) // CROUCH A DEBOUT!!!
{
ImInCrouch = false;
animRobot.CrossFade( "RUN", TimeCrouchToRun, -1, CrossFadeTempo);
Invoke("InitSpeed", AnmSpeedDelais);
} else if ( !ImInCrouch && IsCrouch)
{
ImInCrouch = true;
animRobot.CrossFade( "CROUCH", TimeStandToCrouch, -1, CrossFadeTempo);
Invoke("InitSpeed", AnmSpeedDelais);
} else StartMove();
// Y'a du crouch ici !!!!!!! ******************************
//******************************************************************************
//AnimatorStateInfo animationState = animRobot.GetCurrentAnimatorStateInfo(0);
//AnimatorClipInfo[] myAnimatorClip = animRobot.GetCurrentAnimatorClipInfo(0);
//float myTime = myAnimatorClip[0].clip.length;
//Debug.Log("Retard = " + RetardAnimation + " / Nouveau = " + myTime);
//******************************************************************************
}
void StartMove(){
animRobot.Play(AnmName);
RetardAnimation = AnmDuree; // retard de la prochaine animation (LOOP)
Invoke("LoopMove", RetardAnimation);
Invoke("InitSpeed", AnmSpeedDelais); // Declencher le retard de mouvement duu Perso
}
void InitBlend(){
ImInBlend = true;
LoopMove();
}
void LoopMove() // =============================================================================
{
if (IsArmed){
// Anim mode Armed
if (IsWalk) AnmName = "RIFLE_WALK";;
if (IsRun);
if (IsCrouch);
} else
{
if (IsWalk) AnmName = "WALK";
if (IsRun) AnmName = "RUN";
if (IsCrouch) AnmName = "CROUCH";
}
if (ImInBlend){
if (IsRun) StopMove();
else{
Pg = PiedGauche.position.y; // y
Pd = PiedDroit.position.y; // y
// Debug.Log("> ***Pied Gauche = " + Pg);
// Debug.Log("> ***Pied Droit = " + Pd);
}
float delta = Math.Abs(Pg - Pd);
//if(Pg > Pd) Debug.Log("******************Pied Gauche plus haut de = " + (float)(Pg - Pd)); else Debug.Log("******************Pied Droit plus haut de = " + (float)(Pd - Pg));
if (Pg > Pd) animRobot.CrossFade(AnmName, TimeToBlend, -1, 0.41f + delta); // Debuter l'anim au bon pied en l'air !!!
else animRobot.CrossFade(AnmName, TimeToBlend, -1, CrossFadeTempo);
ImInBlend = false;
} else animRobot.Play(AnmName);
}
void StopMove() // =============================================================================
{
//Transform toto = animRobot.GetBoneTransform(HumanBodyBones.LeftFoot);
//Debug.Log(Pg + " Pied " + toto.position );
Pg = PiedGauche.position.y;
Pd = PiedDroit.position.y;
if (IsArmed){
// Anim mode Armed
if (IsWalk){
AnmStopDelais = 0.6f;
if (Pg > Pd) animRobot.CrossFade("RIFLE_STOP_WALK_GAUCHE", 1.0f, -1, CrossFadeTempo);
else animRobot.CrossFade("RIFLE_STOP_WALK_DROIT", 1.0f, -1, CrossFadeTempo);
}
if (IsRun);
if (IsCrouch);
} else
{ // Anim mode "Civil"
if (IsWalk){
AnmStopDelais = 0.6f;
if (Pg > Pd) animRobot.CrossFade("STOP_WALK_GAUCHE", 1.0f, -1, CrossFadeTempo);
else animRobot.CrossFade("STOP_WALK_DROIT", 1.0f, -1, CrossFadeTempo);
}
if(IsRun){
AnmStopDelais = 0.4f;
if (Pg > Pd) animRobot.CrossFade("STOP_RUN_GAUCHE", 1.0f, -1, CrossFadeTempo);
else animRobot.CrossFade("STOP_RUN_DROIT", 1.0f, -1, CrossFadeTempo);
}
if (IsCrouch){
AnmStopDelais = 0.0f;
if (Pg > Pd) animRobot.CrossFade("STOP_CROUCH_GAUCHE", TimeToCrouchIdle, -1, CrossFadeTempo); // mettre variable ici !!!!!!!!!!!!!!!!!!!!!!!
else animRobot.CrossFade("STOP_CROUCH_DROIT", TimeToCrouchIdle, -1, CrossFadeTempo); // mettre variable ici !!!!!!!!!!!!!!!!!!!!!!!
}
}
if (!ImInBlend){
Invoke("StopVitesse", AnmStopDelais); // DELAI A VOIR !!!
Invoke("IdleMove", 0.6950f); // DELAI A VOIR !!!
}
}
void IdleMove() // ==============================================================================
{
ICanStartMove = false;
ICanStopMove = false;
ICanBlendMove = false;
ImInCrouch = false;
ImInIdle = false;
if (IsArmed){
// Anim mode Armed
if (IsWalk);
if (IsRun);
if (IsCrouch);
} else
{
if (IsWalk || IsRun ){
ImInIdle = true;
UnityEngine.Random.seed = (int)System.DateTime.Now.Millisecond + myID;
IdlePlayTime = Time.time + UnityEngine.Random.Range(8.0f,15.0f); // A VOIR !!!!
// Debug.Log("Time " + Time.time + " / IdlePlayTime = " + IdlePlayTime);
int idleRandom = UnityEngine.Random.Range(1,6);
switch (idleRandom){
case 1:
AnmName = "IDLE1";
break;
case 2:
AnmName = "IDLE2";
break;
case 3:
AnmName = "IDLE3";
break;
case 4:
AnmName = "IDLE4";
break;
case 5:
AnmName = "IDLE5";
break;
case 6:
AnmName = "IDLE6";
break;
}
}
if (IsCrouch){
AnmName = "IDLECROUCH";
ImInCrouch = true;
}
}
animRobot.CrossFade(AnmName, 0.25f, -1, -1); // 0.25f A VOIR !!!
ICanStartMove = true;
}
void InitSpeed() // ===========================================================================
{
Speed = AnmSpeed;
ICanStartMove = false; // DeActiver Move
ICanStopMove = true; // Activer Stop
ICanBlendMove = true;
}
void StopVitesse() // ===========================================================================
{
Speed = 0.0f;
}
void GetWeapon(){
IsWeapon = true;
WeaponLayerWeight = 0.0f;
UnityEngine.Random.seed = (int)System.DateTime.Now.Millisecond;
GetWeaponTime = UnityEngine.Random.Range(0.5f, 0.8f); //
DropWeaponTime = UnityEngine.Random.Range(2.7f, 3.0f); //
animRobot.CrossFade( "GETGUN", 0.1f, -1, CrossFadeTempo);
//animRobot.speed = 0.5f;
//Debug.Log("DropWeaponTime......" + DropWeaponTime);
}
void DropWeapon(){
IsWeapon = false;
animRobot.CrossFade( "DROPGUN", 0.1f, -1, CrossFadeTempo);
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// GESTION ANIM +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// MOON(S) 20.62 MODULE ANIMATION +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++