using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; using UnityEngine.UI; [RequireComponent(typeof(NavMeshAgent), typeof(CharacterController))] public class EnemyController : CharacterBase { public enum AIState { Patrolling, Chasing } public AIState State; public List PatrolPoints; private NavMeshAgent _agent; private Coroutine _attack; private Coroutine _currentAction; public LayerMask PlayerLayer; public Image PlayerDetectIndicator; protected override void Awake() { base.Awake(); _agent = GetComponent(); _agent.speed = Speed; } public bool IsAttacking() { return Display.GetCurrentAnimatorStateInfo(1).IsName("Attack"); } public bool IsRecoil() { return Display.GetCurrentAnimatorStateInfo(0).IsName("Hit"); } protected override void Update() { if (!IsAlive()) return; if (GameManager.Instance == null) return; CharacterBase target = GameManager.Instance.Player; if (_attack != null) return; if (target == null) return; if (State == AIState.Patrolling) { if (_currentAction == null) { Debug.Log("Patrollin"); _currentAction = StartCoroutine(SetNewPatrolPoint()); } else { var detectDistance = 5; var detectAngle = 45; var playerDir = target.transform.position - transform.position; if(Vector3.Angle(transform.forward, playerDir) <= detectAngle && Physics.Raycast(transform.position + Vector3.up * 0.5f, playerDir, detectDistance, PlayerLayer.value)) { PlayerDetectIndicator.fillAmount += Time.deltaTime; if(PlayerDetectIndicator.fillAmount >= 1) { State = AIState.Chasing; } } else { PlayerDetectIndicator.fillAmount -= Time.deltaTime; } } } else if (State == AIState.Chasing) { _agent.SetDestination(target.transform.position); var dist = Vector3.Distance(transform.position, target.transform.position); if (dist < 2.5f) { _attack = StartCoroutine(Attack((target.transform.position - transform.position).normalized)); } } } private IEnumerator Attack(Vector3 moveDirection) { _agent.enabled = false; _cc.enabled = true; Display.PlayState("Attack"); float attackTime = 0; while(attackTime < 2) { _cc.SimpleMove(moveDirection * 5); attackTime += Time.deltaTime; yield return 0; } _cc.enabled = false; _agent.enabled = true; _attack = null; } private IEnumerator SetNewPatrolPoint() { var patrolPoint = PatrolPoints[Random.Range(0, PatrolPoints.Count)]; var bounds = patrolPoint.bounds; var point = new Vector3( Random.Range(bounds.min.x, bounds.max.x), Random.Range(bounds.min.y, bounds.max.y), Random.Range(bounds.min.z, bounds.max.z) ); _agent.SetDestination(point); float timeout = 10f; while (!_agent.isStopped && timeout > 0) { timeout -= Time.deltaTime; yield return 0; } yield return new WaitForSeconds(Random.Range(5f, 10f)); _currentAction = null; } public override void TakeDamage(int dmg) { base.TakeDamage(dmg); if (IsAlive()) { Display.PlayState("Hit"); } } protected override void OnDeath() { Display.PlayState("Die"); _cc.enabled = false; } }