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(); } }