Files
BABA_YAGA/Assets/Scripts/AI NPC/AnimatorAI.cs

164 lines
6.1 KiB
C#
Raw Normal View History

2026-06-05 15:59:33 +07:00
using UnityEngine;
2026-06-05 16:26:04 +07:00
using UnityEngine.AI;
using Invector;
2026-06-05 23:25:56 +07:00
using Invector.vEventSystems;
2026-06-05 16:26:04 +07:00
using System.Collections;
2026-06-06 00:37:41 +07:00
using System.Collections.Generic;
2026-06-05 15:59:33 +07:00
2026-06-05 23:25:56 +07:00
public class AnimatorAI : MonoBehaviour, vIAnimatorStateInfoController
2026-06-05 15:59:33 +07:00
{
2026-06-05 16:26:04 +07:00
protected Animator animator;
protected NavMeshAgent agent;
2026-06-05 23:25:56 +07:00
protected vHealthController healthController;
2026-06-06 00:37:41 +07:00
protected EnemyAI enemyAI;
protected KamikazeAI kamikazeAI;
2026-06-05 16:26:04 +07:00
2026-06-06 00:37:41 +07:00
[Header("Force Settings")]
public bool forceGrounded = true;
public float movementBoost = 1.2f;
public float dampTime = 0.1f;
2026-06-05 23:25:56 +07:00
public vAnimatorStateInfos animatorStateInfos { get; protected set; }
2026-06-05 16:26:04 +07:00
2026-06-06 00:37:41 +07:00
#region Animator Parameters
protected vAnimatorParameter isDead, isGrounded, isStrafing, isSprinting, isAiming;
protected vAnimatorParameter verticalVelocity, horizontalVelocity, inputMagnitude;
protected vAnimatorParameter groundDistance, moveSet_ID, attackID, triggerReaction, resetState;
2026-06-05 16:26:04 +07:00
#endregion
2026-06-05 23:25:56 +07:00
protected Vector3 lastPosition;
2026-06-06 00:37:41 +07:00
protected float currentV, currentH, currentMagnitude, calculatedSpeed;
2026-06-05 22:34:41 +07:00
2026-06-05 23:25:56 +07:00
protected virtual void Awake()
2026-06-05 16:26:04 +07:00
{
animator = GetComponentInChildren<Animator>();
2026-06-06 00:37:41 +07:00
if (animator == null) animator = GetComponentInParent<Animator>();
2026-06-05 16:26:04 +07:00
agent = GetComponent<NavMeshAgent>();
2026-06-06 00:37:41 +07:00
if (agent == null) agent = GetComponentInParent<NavMeshAgent>();
healthController = GetComponentInChildren<vHealthController>();
enemyAI = GetComponent<EnemyAI>();
kamikazeAI = GetComponent<KamikazeAI>();
2026-06-05 16:26:04 +07:00
2026-06-05 23:25:56 +07:00
if (animator)
2026-06-05 16:26:04 +07:00
{
2026-06-06 00:37:41 +07:00
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);
2026-06-05 23:25:56 +07:00
animatorStateInfos = new vAnimatorStateInfos(animator);
InitializeParameters();
2026-06-06 00:37:41 +07:00
Debug.Log($"<color=green>[AnimSystem]</color> Đã kích hoạt trên {gameObject.name}");
2026-06-05 16:26:04 +07:00
}
2026-06-05 16:38:25 +07:00
2026-06-05 23:25:56 +07:00
lastPosition = transform.position;
2026-06-05 16:26:04 +07:00
}
2026-06-06 00:37:41 +07:00
protected virtual void OnEnable() { this.Register(); }
protected virtual void OnDisable() { this.UnRegister(); }
2026-06-05 16:38:25 +07:00
2026-06-05 23:25:56 +07:00
protected virtual void InitializeParameters()
2026-06-05 16:38:25 +07:00
{
2026-06-06 00:37:41 +07:00
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");
2026-06-05 16:26:04 +07:00
}
2026-06-06 00:37:41 +07:00
private vAnimatorParameter ValidateAndInit(string pName) => new vAnimatorParameter(animator, pName);
2026-06-05 16:26:04 +07:00
protected virtual void Update()
{
2026-06-06 00:37:41 +07:00
if (animator == null || agent == null) return;
2026-06-05 16:26:04 +07:00
2026-06-05 23:25:56 +07:00
UpdateMovementParameters();
UpdateCombatParameters();
2026-06-05 16:26:04 +07:00
}
2026-06-05 23:25:56 +07:00
protected virtual void UpdateMovementParameters()
2026-06-05 16:26:04 +07:00
{
2026-06-06 00:37:41 +07:00
SetBool(isGrounded, forceGrounded);
SetFloat(groundDistance, 0f);
2026-06-05 16:26:04 +07:00
2026-06-06 00:37:41 +07:00
Vector3 delta = transform.position - lastPosition;
calculatedSpeed = delta.magnitude / Time.deltaTime;
lastPosition = transform.position;
2026-06-05 16:26:04 +07:00
2026-06-06 00:37:41 +07:00
Vector3 localVel = transform.InverseTransformDirection(delta / Time.deltaTime);
2026-06-05 23:25:56 +07:00
2026-06-06 00:37:41 +07:00
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;
2026-06-05 23:25:56 +07:00
currentV = Mathf.Lerp(currentV, targetV, 10f * Time.deltaTime);
currentH = Mathf.Lerp(currentH, targetH, 10f * Time.deltaTime);
2026-06-06 00:37:41 +07:00
currentMagnitude = new Vector2(currentH, currentV).magnitude;
2026-06-05 16:26:04 +07:00
2026-06-06 00:37:41 +07:00
// ÉP GIÁ TRỊ VÀO ANIMATOR
2026-06-05 23:25:56 +07:00
SetFloat(verticalVelocity, currentV);
SetFloat(horizontalVelocity, currentH);
2026-06-06 00:37:41 +07:00
SetFloat(inputMagnitude, currentMagnitude);
2026-06-05 16:26:04 +07:00
}
protected virtual void UpdateCombatParameters()
{
2026-06-06 00:37:41 +07:00
// 1. Kiểm tra trạng thái AI
bool isShooting = (enemyAI && enemyAI.IsShootingBurst);
bool hasArtifact = (enemyAI && enemyAI.playerHasArtifact);
2026-06-05 16:26:04 +07:00
2026-06-06 00:37:41 +07:00
// 2. Cập nhật MoveSet và Aiming
SetInt(moveSet_ID, hasArtifact ? 1 : 0);
SetBool(isAiming, hasArtifact);
SetBool(isStrafing, hasArtifact);
2026-06-05 23:25:56 +07:00
2026-06-06 00:37:41 +07:00
// 3. Xử lý BẮN SÚNG (Layer 6 trong Animator của bạn)
if (isShooting)
2026-06-05 23:25:56 +07:00
{
2026-06-06 00:37:41 +07:00
// 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
2026-06-05 23:25:56 +07:00
}
2026-06-06 00:37:41 +07:00
else
2026-06-05 16:26:04 +07:00
{
2026-06-06 00:37:41 +07:00
// Tắt Layer bắn súng về 0
animator.SetLayerWeight(6, Mathf.Lerp(animator.GetLayerWeight(6), 0f, 10f * Time.deltaTime));
SetInt(attackID, 0);
2026-06-05 16:26:04 +07:00
}
2026-06-05 23:25:56 +07:00
2026-06-06 00:37:41 +07:00
if (enemyAI && enemyAI.IsDodging) SetAnimatorTrigger(triggerReaction);
2026-06-05 15:59:33 +07:00
}
2026-06-05 23:25:56 +07:00
#region Helpers
2026-06-06 00:37:41 +07:00
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));
2026-06-05 23:25:56 +07:00
}
2026-06-06 00:37:41 +07:00
private IEnumerator SetTriggerRoutine(int targetHash)
{
animator.SetTrigger(targetHash);
yield return new WaitForSeconds(0.1f);
animator.ResetTrigger(targetHash);
2026-06-05 16:26:04 +07:00
}
#endregion
2026-06-05 15:59:33 +07:00
}