Character-code-sample/Characters/EnemyController.cs

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;
}
}