using System; using System.Collections; using System.Collections.Generic; using System.Text; using UnityEngine; using Cysharp.Threading.Tasks; using System.Threading; using System.Threading.Tasks; using Unity.Mathematics; namespace BITKit.Animations { public class UnityAnimator : MonoBehaviour, IAnimator { [Serializable] public class AnimatorLayerInfo { public string LayerName; public string stateName; public string fullStateName; internal string entryName; public AnimatorStateInfo currentState = new(); public event Action onStateEnter; public event Action onStateExit; public void OnStateEnter(string name) { onStateEnter?.Invoke(name); } public void OnStateExit(string name) { onStateExit?.Invoke(name); } } [Header(Constant.Header.Settings)] [SerializeField] private bool debug; [Header(Constant.Header.Components)] public Animator animator; public AnimatorLayerInfo this[int index] { get { if (layerInfos.Count <= index) { for (int i = layerInfos.Count - 1; i < index; i++) { var newLayer = new AnimatorLayerInfo { LayerName = animator.GetLayerName(i+1) }; layerInfos.Add(newLayer); } } if (index > layerInfos.Count - 1) { throw new Exception("Index out of range"); } return layerInfos[index]; } } [SerializeField] private List layerInfos = new(); [Header(Constant.Header.InternalVariables)] private readonly Dictionary _registryStates=new (); private void OnEnable() { animator.enabled = true; } private void OnDisable() { animator.enabled = false; foreach (var x in layerInfos) { x.entryName = null; } } public void CrossFade(string animationName, float duration, int index = 0, float normalizedTimeOffset = 0) { animator.CrossFade(GetVariableName(animationName), duration, index, normalizedTimeOffset); } public void Play(string animationName, int index = -1, float normalizedTimeOffset = 0) { if (debug) { BIT4Log.Log( $"{gameObject.name} Play:" + animationName); } animator.Play(GetVariableName(animationName), index, normalizedTimeOffset); } public void OnStateEnter(int index, string name) { if (debug) { BIT4Log.Log($"OnEntry:{name}"); } this[index].fullStateName = name; foreach (var item in name.Split(".")) { name = item; break; } this[index].stateName = this[index].entryName = name; this[index].OnStateEnter(name); } public void OnStateExit(int index, string name) { if (string.IsNullOrEmpty(this[index].entryName)) { return; } if (debug) { BIT4Log.Log($"OnExit:{name}"); } this[index].OnStateExit(name); } public float3 GetRootVelocity() { return animator.velocity; } private void Start() { foreach (var x in animator.GetBehaviours()) { try { _registryStates.TryAdd(x.StateName, x); foreach (var v in x.VariableNames) { _registryStates.TryAdd(v, x); } } catch (Exception e) { BIT4Log.Warning(gameObject.name); throw; } } } private void Update() { for (var i = 0; i < animator.layerCount; i++) { this[i].currentState = animator.GetCurrentAnimatorStateInfo(i); } } [ContextMenu(nameof(Diagnosis))] private void Diagnosis() { } private string GetVariableName(string animationName) { animationName = animationName.Replace(".", "_"); if (!_registryStates.TryGetValue(animationName, out var stateInfo)) return animationName; animationName = stateInfo.StateName; if (stateInfo.VariableAnimationNames.Length > 0) { animationName = stateInfo.VariableAnimationNames.Random(); } return animationName; } } }