145 lines
3.9 KiB
C#
145 lines
3.9 KiB
C#
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<Collider> PatrolPoints;
|
|
private NavMeshAgent _agent;
|
|
private Coroutine _attack;
|
|
private Coroutine _currentAction;
|
|
public LayerMask PlayerLayer;
|
|
public Image PlayerDetectIndicator;
|
|
|
|
protected override void Awake()
|
|
{
|
|
base.Awake();
|
|
_agent = GetComponent<NavMeshAgent>();
|
|
_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;
|
|
}
|
|
}
|