From 8e40d215d62494f2f8673a48b6fe9855d2aed855 Mon Sep 17 00:00:00 2001 From: manhduyhoang90 Date: Fri, 5 Jun 2026 22:53:48 +0700 Subject: [PATCH] Update EnemyAI.cs --- Assets/Scripts/AI NPC/EnemyAI.cs | 46 +++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/Assets/Scripts/AI NPC/EnemyAI.cs b/Assets/Scripts/AI NPC/EnemyAI.cs index 8906a533..ffe02250 100644 --- a/Assets/Scripts/AI NPC/EnemyAI.cs +++ b/Assets/Scripts/AI NPC/EnemyAI.cs @@ -51,14 +51,16 @@ public class EnemyAI : MonoBehaviour private float nextDodgeTime = 0f; [Header("Artifact Combat Upgrades (New)")] - [Tooltip("Khoảng cách di chuyển trái/phải ngẫu nhiên qua thời gian duy trì")] public float minStrafeDuration = 0.5f; public float maxStrafeDuration = 2.2f; - [Tooltip("Độ lệch tâm bắn (Độ). Số càng nhỏ bắn càng chuẩn, số lớn bắn càng lệch")] public float maxSpreadAngle = 6f; - [Tooltip("Tốc độ bắn giữa các viên trong cùng 1 loạt đạn")] public float burstInterval = 0.12f; + public float approachWeight = 0.35f; + public float minCombatDistance = 5.0f; + + + private float nextStrafeChangeTime; private int strafeDirectionSign = 1; // -1: Trái, 1: Phải, 0: Đứng im bắn private bool isShootingBurst = false; // Khóa chống trùng lặp loạt bắn @@ -337,7 +339,7 @@ public class EnemyAI : MonoBehaviour private NodeState ActionFocusAndShoot() { - if (player == null) return NodeState.Failure; + if (player == null) return NodeState.Failure; if (agent.hasPath) agent.ResetPath(); agent.isStopped = false; @@ -352,24 +354,40 @@ public class EnemyAI : MonoBehaviour transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotateSpeed * Time.deltaTime); } - // 2. RANDOM KHOẢNG CÁCH DI CHUYỂN TRÁI/PHẢI (Tính theo thời gian duy trì) + // 2. RANDOM THỜI GIAN/KHOẢNG CÁCH DUY TRÌ HƯỚNG DI CHUYỂN if (Time.time >= nextStrafeChangeTime) { int[] choices = { -1, 1, 0 }; // Trái, Phải, Đứng yên bắn strafeDirectionSign = choices[Random.Range(0, choices.Length)]; - - // Ép khoảng cách di chuyển dài ngắn ngẫu nhiên bằng cách random thời gian đổi hướng nextStrafeChangeTime = Time.time + Random.Range(minStrafeDuration, maxStrafeDuration); } + // 3. TÍNH TOÁN TRỘN VECTOR: CHỈ TIẾN LÊN KHI ĐANG ĐI NGANG TRÁI/PHẢI + Vector3 finalMovementVector = Vector3.zero; + + // Kiểm tra xem AI có đang di chuyển ngang không (strafeDirectionSign khác 0) if (strafeDirectionSign != 0 && bodyDir != Vector3.zero) { - Vector3 strafeDir = new Vector3(-bodyDirNormal.z, 0, bodyDirNormal.x) * strafeDirectionSign; - agent.speed = moveSpeed * 0.75f; - agent.Move(strafeDir * agent.speed * Time.deltaTime); + // Vector đi ngang trái/phải + finalMovementVector = new Vector3(-bodyDirNormal.z, 0, bodyDirNormal.x) * strafeDirectionSign; + + // Tiến tới tịnh tiến dần dần nếu chưa đạt khoảng cách tối thiểu + float currentDistance = Vector3.Distance(transform.position, player.position); + if (currentDistance > minCombatDistance) + { + finalMovementVector += bodyDirNormal * approachWeight; + } } - // 3. XOAY HỌNG SÚNG TRỤC DỌC NHẮM VÀO NGƯỜI PLAYER + // Áp dụng di chuyển thực tế bằng Agent.Move + if (finalMovementVector != Vector3.zero) + { + finalMovementVector.Normalize(); // Chuẩn hóa vector + agent.speed = moveSpeed * 0.75f; + agent.Move(finalMovementVector * agent.speed * Time.deltaTime); + } + + // 4. XOAY HỌNG SÚNG TRỤC DỌC NHẮM VÀO NGƯỜI PLAYER if (firePoint != null) { Vector3 targetCenter = player.position + Vector3.up * 1f; @@ -380,13 +398,11 @@ public class EnemyAI : MonoBehaviour } } - // 4. RANDOM SỐ ĐẠN (1-3) & RANDOM DELAY GIỮA CÁC ĐỢT BẮN + // 5. RANDOM SỐ ĐẠN & DELAY GIỮA CÁC ĐỢT BẮN if (Time.time >= nextShootTime && !isShootingBurst) { - int randomBulletCount = Random.Range(1, 4); // Trả về ngẫu nhiên 1, 2, hoặc 3 viên + int randomBulletCount = Random.Range(1, 4); StartCoroutine(ShootBurstRoutine(randomBulletCount)); - - // Cập nhật thời gian chờ cho loạt đạn tiếp theo (Random delay) nextShootTime = Time.time + Random.Range(minShootDelay, maxShootDelay); }