using System; using System.Collections; using System.Collections.Generic; using UnityEngine; // ReSharper disable once CheckNamespace namespace BlueWaterProject { public enum CombatPlayerAnimatorParameter { X_DIRECTION, Z_DIRECTION, IS_MOVING, IS_DASHING, IS_READY_MAIN_SKILL, IS_ACTIVATE_MAIN_SKILL, COMBO_ATTACK_COUNT } public enum CombatPlayerAnimationName { DASH_STATE, COMBO_ATTACK1, COMBO_ATTACK2, READY_TO_MAIN_SKILL, MAIN_SKILL } public class CombatAnimator : MonoBehaviour, IAnimationStateController { // Components private Animator anim; // Dictionaries private Dictionary animationParameterHashDictionary = new(); private Dictionary animationNameHashDictionary = new(); // Parameter hashes private static readonly int XDirectionHash = Animator.StringToHash("xDirection"); private static readonly int ZDirectionHash = Animator.StringToHash("zDirection"); private static readonly int IsMovingHash = Animator.StringToHash("isMoving"); private static readonly int IsDashingHash = Animator.StringToHash("isDashing"); private static readonly int IsReadyMainSkillHash = Animator.StringToHash("isReadyMainSkill"); private static readonly int IsActivateMainSkillHash = Animator.StringToHash("isActivateMainSkill"); private static readonly int ComboAttackCount = Animator.StringToHash("ComboAttackCount"); // Animation name hashes private static readonly int DashStateHash = Animator.StringToHash("DashState"); private static readonly int ComboAttack1Hash = Animator.StringToHash("ComboAttack1"); private static readonly int ComboAttack2Hash = Animator.StringToHash("ComboAttack2"); private static readonly int ReadyToMainSkillHash = Animator.StringToHash("ReadyToMainSkill"); private static readonly int MainSkillHash = Animator.StringToHash("MainSkill"); // Unity events private void Awake() { InitDictionary(); } // Init public void InitComponent(Animator animator) { anim = animator; } private void InitDictionary() { animationParameterHashDictionary = new Dictionary(Enum.GetValues(typeof(CombatPlayerAnimatorParameter)).Length) { { CombatPlayerAnimatorParameter.X_DIRECTION, XDirectionHash }, { CombatPlayerAnimatorParameter.Z_DIRECTION, ZDirectionHash }, { CombatPlayerAnimatorParameter.IS_MOVING, IsMovingHash }, { CombatPlayerAnimatorParameter.IS_DASHING, IsDashingHash }, { CombatPlayerAnimatorParameter.IS_READY_MAIN_SKILL, IsReadyMainSkillHash }, { CombatPlayerAnimatorParameter.IS_ACTIVATE_MAIN_SKILL, IsActivateMainSkillHash }, { CombatPlayerAnimatorParameter.COMBO_ATTACK_COUNT, ComboAttackCount } }; animationNameHashDictionary = new Dictionary(Enum.GetValues(typeof(CombatPlayerAnimationName)).Length) { { CombatPlayerAnimationName.DASH_STATE, DashStateHash }, { CombatPlayerAnimationName.COMBO_ATTACK1, ComboAttack1Hash }, { CombatPlayerAnimationName.COMBO_ATTACK2, ComboAttack2Hash }, { CombatPlayerAnimationName.READY_TO_MAIN_SKILL, ReadyToMainSkillHash }, { CombatPlayerAnimationName.MAIN_SKILL, MainSkillHash } }; } // Methods public void SetAnimationParameter(T parameter, bool value) { if (parameter is CombatPlayerAnimatorParameter enumParameter) { anim.SetBool(animationParameterHashDictionary[enumParameter], value); } else { throw new ArgumentException("Invalid parameter type for SetAnimationParameter"); } } public void SetAnimationParameter(T parameter, int value) { if (parameter is CombatPlayerAnimatorParameter enumParameter) { anim.SetInteger(animationParameterHashDictionary[enumParameter], value); } else { throw new ArgumentException("Invalid parameter type for SetAnimationParameter"); } } public void SetAnimationParameter(T parameter, float value) { if (parameter is CombatPlayerAnimatorParameter enumParameter) { anim.SetFloat(animationParameterHashDictionary[enumParameter], value); } else { throw new ArgumentException("Invalid parameter type for SetAnimationParameter"); } } public void SetAnimationTrigger(T parameter) { if (parameter is CombatPlayerAnimatorParameter enumParameter) { anim.SetTrigger(animationParameterHashDictionary[enumParameter]); } else { throw new ArgumentException("Invalid parameter type for SetAnimationParameter"); } } public void ResetAnimationSpeed() { anim.speed = 1f; } public bool IsComparingCurrentAnimation(string animationName, int animatorLayer = 0) { return anim.GetCurrentAnimatorStateInfo(animatorLayer).IsName(animationName); } public bool IsComparingCurrentAnimation(T animationName, int animatorLayer = 0) { if (animationName is CombatPlayerAnimationName enumAnimationName) { return anim.GetCurrentAnimatorStateInfo(animatorLayer).shortNameHash == animationNameHashDictionary[enumAnimationName]; } throw new ArgumentException("Invalid parameter type for SetAnimationParameter"); } public IEnumerator WaitForAnimationToRun(string animationName, Action onSuccess, float timeout = 0.2f) { var elapsedTime = 0f; while (!IsComparingCurrentAnimation(animationName)) { elapsedTime += Time.deltaTime; yield return null; if (elapsedTime <= timeout) continue; print("Timeout waiting for animation state: " + animationName); onSuccess?.Invoke(false); } onSuccess?.Invoke(true); } public IEnumerator WaitForAnimationToRun(T animationName, Action onSuccess, float timeout = 0.2f) { var elapsedTime = 0f; while (!IsComparingCurrentAnimation(animationName)) { elapsedTime += Time.deltaTime; yield return null; if (elapsedTime <= timeout) continue; print("Timeout waiting for animation state: " + animationName); onSuccess?.Invoke(false); } onSuccess?.Invoke(true); } public void SetCurrentAnimationSpeed(float targetDuration, int animatorLayer = 0) { var animationLength = anim.GetCurrentAnimatorStateInfo(animatorLayer).length; anim.speed = animationLength / targetDuration; } public float GetCurrentAnimationNormalizedTime(int animatorLayer = 0) { return anim.GetCurrentAnimatorStateInfo(animatorLayer).normalizedTime; } } }