using UnityEngine; using UnityEngine.AI; using Invector; using Invector.vEventSystems; using System.Collections; using System.Collections.Generic; public class AnimatorAI : MonoBehaviour, vIAnimatorStateInfoController { protected Animator animator; protected NavMeshAgent agent; protected vHealthController healthController; protected EnemyAI enemyAI; protected KamikazeAI kamikazeAI; [Header("Force Settings")] public bool forceGrounded = true; public float movementBoost = 1.2f; public float dampTime = 0.1f; public vAnimatorStateInfos animatorStateInfos { get; protected set; } #region Animator Parameters protected vAnimatorParameter isDead, isGrounded, isStrafing, isSprinting, isAiming; protected vAnimatorParameter verticalVelocity, horizontalVelocity, inputMagnitude; protected vAnimatorParameter groundDistance, moveSet_ID, attackID, triggerReaction, resetState; #endregion protected Vector3 lastPosition; protected float currentV, currentH, currentMagnitude, calculatedSpeed; protected virtual void Awake() { animator = GetComponentInChildren(); if (animator == null) animator = GetComponentInParent(); agent = GetComponent(); if (agent == null) agent = GetComponentInParent(); healthController = GetComponentInChildren(); enemyAI = GetComponent(); kamikazeAI = GetComponent(); if (animator) { animator.applyRootMotion = false; animator.updateMode = AnimatorUpdateMode.Normal; // Reset all layers initially to prevent T-Pose for (int i = 1; i < animator.layerCount; i++) animator.SetLayerWeight(i, 0f); animatorStateInfos = new vAnimatorStateInfos(animator); InitializeParameters(); Debug.Log($"[AnimSystem] Đã kích hoạt trên {gameObject.name}"); } lastPosition = transform.position; } protected virtual void OnEnable() { this.Register(); } protected virtual void OnDisable() { this.UnRegister(); } protected virtual void InitializeParameters() { isDead = ValidateAndInit("isDead"); isGrounded = ValidateAndInit("isGrounded"); if (!isGrounded.isValid) isGrounded = ValidateAndInit("IsGrounded"); isStrafing = ValidateAndInit("IsStrafing"); isSprinting = ValidateAndInit("IsSprinting"); isAiming = ValidateAndInit("IsAiming"); verticalVelocity = ValidateAndInit("InputVertical"); horizontalVelocity = ValidateAndInit("InputHorizontal"); inputMagnitude = ValidateAndInit("InputMagnitude"); groundDistance = ValidateAndInit("GroundDistance"); moveSet_ID = ValidateAndInit("MoveSet_ID"); attackID = ValidateAndInit("AttackID"); triggerReaction = ValidateAndInit("TriggerReaction"); resetState = ValidateAndInit("ResetState"); } private vAnimatorParameter ValidateAndInit(string pName) => new vAnimatorParameter(animator, pName); protected virtual void Update() { if (animator == null || agent == null) return; UpdateMovementParameters(); UpdateCombatParameters(); } protected virtual void UpdateMovementParameters() { SetBool(isGrounded, forceGrounded); SetFloat(groundDistance, 0f); Vector3 delta = transform.position - lastPosition; calculatedSpeed = delta.magnitude / Time.deltaTime; lastPosition = transform.position; Vector3 localVel = transform.InverseTransformDirection(delta / Time.deltaTime); float maxS = (enemyAI) ? enemyAI.moveSpeed : (kamikazeAI ? agent.speed : 3f); if (maxS <= 0) maxS = 3f; float targetV = (localVel.z / maxS) * movementBoost; float targetH = (localVel.x / maxS) * movementBoost; currentV = Mathf.Lerp(currentV, targetV, 10f * Time.deltaTime); currentH = Mathf.Lerp(currentH, targetH, 10f * Time.deltaTime); currentMagnitude = new Vector2(currentH, currentV).magnitude; // ÉP GIÁ TRỊ VÀO ANIMATOR SetFloat(verticalVelocity, currentV); SetFloat(horizontalVelocity, currentH); SetFloat(inputMagnitude, currentMagnitude); } protected virtual void UpdateCombatParameters() { // 1. Kiểm tra trạng thái AI bool isShooting = (enemyAI && enemyAI.IsShootingBurst); bool hasArtifact = (enemyAI && enemyAI.playerHasArtifact); // 2. Cập nhật MoveSet và Aiming SetInt(moveSet_ID, hasArtifact ? 1 : 0); SetBool(isAiming, hasArtifact); SetBool(isStrafing, hasArtifact); // 3. Xử lý BẮN SÚNG (Layer 6 trong Animator của bạn) if (isShooting) { // Bật Layer bắn súng lên 1 (Smooth) animator.SetLayerWeight(6, Mathf.Lerp(animator.GetLayerWeight(6), 1f, 15f * Time.deltaTime)); SetInt(attackID, 1); // Kích hoạt animation bắn trong Blend Tree của Layer 6 } else { // Tắt Layer bắn súng về 0 animator.SetLayerWeight(6, Mathf.Lerp(animator.GetLayerWeight(6), 0f, 10f * Time.deltaTime)); SetInt(attackID, 0); } if (enemyAI && enemyAI.IsDodging) SetAnimatorTrigger(triggerReaction); } #region Helpers protected void SetBool(vAnimatorParameter p, bool v) { if (p.isValid) animator.SetBool(p, v); } protected void SetFloat(vAnimatorParameter p, float v) { if (p.isValid) animator.SetFloat(p, v, dampTime, Time.deltaTime); } protected void SetInt(vAnimatorParameter p, int v) { if (p.isValid) animator.SetInteger(p, v); } public void SetAnimatorTrigger(vAnimatorParameter trigger) { if (trigger.isValid) StartCoroutine(SetTriggerRoutine(trigger)); } private IEnumerator SetTriggerRoutine(int targetHash) { animator.SetTrigger(targetHash); yield return new WaitForSeconds(0.1f); animator.ResetTrigger(targetHash); } #endregion }