using UnityEngine; using UnityEngine.AI; [RequireComponent(typeof(CharacterController))] public class EnemyAI : MonoBehaviour { public CaptureZone[] zones; public float moveSpeed = 3.5f; public float retargetInterval = 2f; public float stoppingDistance = 0.7f; public float randomFactor = 4f; private CharacterController characterController; private NavMeshAgent navMeshAgent; private CaptureZone targetZone; private Vector3 targetOffset; private float retargetTimer; private Vector3 verticalVelocity; private void Awake() { characterController = GetComponent(); navMeshAgent = GetComponent(); if (navMeshAgent != null) { navMeshAgent.speed = moveSpeed; navMeshAgent.stoppingDistance = stoppingDistance; } } private void Start() { ChooseTarget(); } private void Update() { retargetTimer -= Time.deltaTime; if (targetZone == null || targetZone.GetOwner() == CaptureZone.Owner.Enemy || retargetTimer <= 0f) { ChooseTarget(); } MoveToTarget(); } private void ChooseTarget() { retargetTimer = retargetInterval + Random.Range(0f, 0.75f); targetZone = null; CaptureZone bestPlayerZone = FindBestZone(CaptureZone.Owner.Player); if (bestPlayerZone != null) { SetTarget(bestPlayerZone); return; } CaptureZone bestNeutralZone = FindBestZone(CaptureZone.Owner.Neutral); if (bestNeutralZone != null) { SetTarget(bestNeutralZone); } } private CaptureZone FindBestZone(CaptureZone.Owner owner) { if (zones == null || zones.Length == 0) { return null; } CaptureZone best = null; float bestScore = float.MaxValue; for (int i = 0; i < zones.Length; i++) { CaptureZone zone = zones[i]; if (zone == null || zone.GetOwner() != owner) { continue; } float distance = Vector3.Distance(transform.position, zone.transform.position); float score = distance + Random.Range(0f, randomFactor); if (score < bestScore) { bestScore = score; best = zone; } } return best; } private void SetTarget(CaptureZone zone) { targetZone = zone; Vector2 randomCircle = Random.insideUnitCircle * 1.5f; targetOffset = new Vector3(randomCircle.x, 0f, randomCircle.y); if (CanUseNavMeshAgent()) { navMeshAgent.SetDestination(GetTargetPosition()); } } private void MoveToTarget() { if (targetZone == null) { return; } Vector3 targetPosition = GetTargetPosition(); if (CanUseNavMeshAgent()) { if (!navMeshAgent.hasPath || Vector3.Distance(navMeshAgent.destination, targetPosition) > 0.5f) { navMeshAgent.SetDestination(targetPosition); } return; } Vector3 direction = targetPosition - transform.position; direction.y = 0f; if (direction.magnitude <= stoppingDistance) { return; } Vector3 horizontalMove = direction.normalized * moveSpeed; if (characterController.isGrounded && verticalVelocity.y < 0f) { verticalVelocity.y = -1f; } verticalVelocity.y += Physics.gravity.y * Time.deltaTime; characterController.Move((horizontalMove + verticalVelocity) * Time.deltaTime); if (horizontalMove.sqrMagnitude > 0.001f) { transform.rotation = Quaternion.LookRotation(horizontalMove.normalized, Vector3.up); } } private Vector3 GetTargetPosition() { return targetZone.transform.position + targetOffset; } private bool CanUseNavMeshAgent() { return navMeshAgent != null && navMeshAgent.enabled && navMeshAgent.isActiveAndEnabled && navMeshAgent.isOnNavMesh; } }