128 lines
3.4 KiB
C#
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);
|
|
}
|
|
}
|
|
} |