FPSGame/Assets/Enemies/EnemyAI.cs

128 lines
3.4 KiB
C#

using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.AI;
public class EnemyAI : MonoBehaviour, IAggroable
{
[Header("Configuration")]
[SerializeField] private float _detectRange = 15f;
[SerializeField] private float _attackRange = 5f;
[SerializeField] private float _rotationSpeed = 0.1f;
[Header("State")]
[SerializeField] private Transform _target;
[SerializeField] private bool _isProvoked;
[SerializeField] private bool _isDead;
private NavMeshAgent _navMeshAgent;
private Animator _animator;
private EnemyHealth _enemyHealth;
private static readonly int MoveAnimation = Animator.StringToHash("Move");
private static readonly int AttackAnimation = Animator.StringToHash("Attack");
private static readonly int IdleAnimation = Animator.StringToHash("Idle");
private static readonly int DeathAnimation = Animator.StringToHash("Die");
public bool IsProvoked
{
get => _isProvoked;
set => _isProvoked = value;
}
private void Awake()
{
_target = FindObjectOfType<PlayerHealth>().transform;
}
private void Start()
{
_navMeshAgent = GetComponent<NavMeshAgent>();
_animator = GetComponent<Animator>();
_enemyHealth = GetComponent<EnemyHealth>();
SetStopDistance(_attackRange * 0.9f);
}
private void Update()
{
if (!_isDead)
{
if (DistanceToTarget(_target.position) < _detectRange)
{
_isProvoked = true;
}
if (_isProvoked)
{
EngageTarget();
}
if (_enemyHealth.IsDead)
{
_animator.SetTrigger(DeathAnimation);
_navMeshAgent.isStopped = true;
_isDead = true;
}
}
}
private void EngageTarget()
{
if (DistanceToTarget(_target.position) <= _attackRange)
{
AttackTarget();
}
else if (_isProvoked)
{
FollowTarget();
}
else
{
Idle();
}
}
private void FollowTarget()
{
_animator.SetTrigger(MoveAnimation);
_animator.SetBool(AttackAnimation, false);
_navMeshAgent.SetDestination(_target.position);
}
private void AttackTarget()
{
_animator.SetBool(AttackAnimation, true);
FaceTarget();
//print("Die Human!");
}
private void Idle()
{
_animator.SetTrigger(IdleAnimation);
}
private void SetStopDistance(float stopDistance)
{
_navMeshAgent.stoppingDistance = stopDistance;
}
private float DistanceToTarget(Vector3 targetPosition)
{
return Vector3.Distance(gameObject.transform.position, targetPosition);
}
private void FaceTarget()
{
Vector3 direction = (_target.position - transform.position).normalized;
Quaternion lookRotation = Quaternion.LookRotation(new Vector3(direction.x, 0, direction.z));
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * _rotationSpeed);
}
void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, _detectRange);
if (_navMeshAgent != null)
{
Gizmos.color = Color.blue;
Gizmos.DrawWireSphere(transform.position, _navMeshAgent.stoppingDistance);
}
}
}