using UnityEngine;
using System.Collections.Generic;
using System.Collections;
#if UNITY_EDITOR
using UnityEditor.Animations;
#endif
namespace VRSDK
{
///
/// This scripts helps handling the Animator
///
public class AnimatorHelper : MonoBehaviour
{
[SerializeField] private List animatorControllerInfo = null;
[SerializeField] private float layerTransitionTime = 0.15f;
private Animator animator = null;
private Coroutine changeLayerValueCoroutine = null;
private void Awake()
{
animator = GetComponent();
}
///
/// Do smooth layer transition
///
public void EnableLayer(int layer)
{
if (changeLayerValueCoroutine != null)
StopCoroutine( changeLayerValueCoroutine );
changeLayerValueCoroutine = StartCoroutine( ChangeLayerValueRoutine( layer, 1.0f, layerTransitionTime ) );
}
///
/// Do smooth layer transition
///
public void DisableLayer(int layer)
{
if (changeLayerValueCoroutine != null)
StopCoroutine( changeLayerValueCoroutine );
changeLayerValueCoroutine = StartCoroutine( ChangeLayerValueRoutine( layer, 0.0f, layerTransitionTime ) );
}
private IEnumerator ChangeLayerValueRoutine(int layer, float v, float t)
{
float timer = 0.0f;
while (timer < t)
{
float layerWeight = animator.GetLayerWeight( layer );
animator.SetLayerWeight( layer, Mathf.Lerp( layerWeight, v, timer / t ) );
timer += Time.deltaTime;
yield return new WaitForSeconds( Time.deltaTime );
}
animator.SetLayerWeight( layer, v );
}
///
/// This method is really helpfull, you can know whethever the animator is playing certain state or trasition to it
///
public bool IsPlayingOrTransitionToState(int layer , string stateName)
{
return IsPlayingState( layer, stateName ) || IsTransitionToState(layer , stateName);
}
///
/// is the state name in layer being played?
///
public bool IsPlayingState(int layer , string stateName)
{
return animator.GetCurrentAnimatorStateInfo( layer ).IsName( stateName );
}
///
/// Is animator trasition to current state in layer
///
public bool IsTransitionToState(int layer , string stateName)
{
List states = animatorControllerInfo[layer].animatorStates;
for (int n = 0; n < states.Count; n++)
{
if (animator.GetAnimatorTransitionInfo( layer ).IsName( states[n] + " -> " + stateName ))
return true;
}
return false;
}
#if UNITY_EDITOR
/// in order to know if the animator is trasition to another state we need to know all state names before hand
/// but we can only know them using using UnityEditor.Animations namespace, so we ned to build this information in Editor
/// and serialized it so we can access it later in running time, this method is called in I_AnimatorHelperInspector.cs in the Awake
public void ConstructAnimatorControllerInfo()
{
animatorControllerInfo = new List();
AnimatorController ac = GetComponent().runtimeAnimatorController as AnimatorController;
AnimatorControllerLayer[] layerArray = ac.layers;
for (int n = 0; n < layerArray.Length; n++)
{
LayerInfo info = new LayerInfo();
info.animatorStates = GetStatesFromLayer( layerArray[n] ); ;
animatorControllerInfo.Add(info);
}
}
private List GetStatesFromLayer(AnimatorControllerLayer layer)
{
List states = new List();
for (int n = 0; n < layer.stateMachine.states.Length; n++)
{
states.Add( layer.stateMachine.states[n].state.name );
}
return states;
}
#endif
}
///
/// serialize class for storing animator state names
///
[System.Serializable]
public class LayerInfo
{
public List animatorStates = new List();
}
}