110 lines
4.1 KiB
C#
110 lines
4.1 KiB
C#
using UnityEngine;
|
||
using UnityEngine.AI; // Важно: добавляем пространство имен для работы с NavMesh
|
||
|
||
public class EnemyAI : MonoBehaviour
|
||
{
|
||
public NavMeshAgent agent;
|
||
public Transform player;
|
||
public LayerMask whatIsGround, whatIsPlayer;
|
||
|
||
// Патрулирование
|
||
public Vector3 walkPoint;
|
||
bool walkPointSet;
|
||
public float walkPointRange;
|
||
|
||
// Атака
|
||
public float timeBetweenAttacks;
|
||
bool alreadyAttacked;
|
||
public GameObject projectile; // Враг будет стрелять объектами, а не рэйкастом для наглядности
|
||
|
||
// Состояния
|
||
public float sightRange, attackRange;
|
||
public bool playerInSightRange, playerInAttackRange;
|
||
|
||
private void Awake()
|
||
{
|
||
player = GameObject.Find("Player").transform; // Находим игрока по имени
|
||
agent = GetComponent<NavMeshAgent>();
|
||
}
|
||
|
||
private void Update()
|
||
{
|
||
// Проверяем, находится ли игрок в зоне видимости и в зоне атаки
|
||
playerInSightRange = Physics.CheckSphere(transform.position, sightRange, whatIsPlayer);
|
||
playerInAttackRange = Physics.CheckSphere(transform.position, attackRange, whatIsPlayer);
|
||
|
||
if (!playerInSightRange && !playerInAttackRange) Patroling();
|
||
if (playerInSightRange && !playerInAttackRange) ChasePlayer();
|
||
if (playerInAttackRange && playerInSightRange) AttackPlayer();
|
||
}
|
||
|
||
private void Patroling()
|
||
{
|
||
if (!walkPointSet) SearchWalkPoint();
|
||
|
||
if (walkPointSet)
|
||
agent.SetDestination(walkPoint);
|
||
|
||
Vector3 distanceToWalkPoint = transform.position - walkPoint;
|
||
|
||
// Точка достигнута
|
||
if (distanceToWalkPoint.magnitude < 1f)
|
||
walkPointSet = false;
|
||
}
|
||
|
||
private void SearchWalkPoint()
|
||
{
|
||
// Ищем случайную точку в заданном диапазоне
|
||
float randomZ = Random.Range(-walkPointRange, walkPointRange);
|
||
float randomX = Random.Range(-walkPointRange, walkPointRange);
|
||
|
||
walkPoint = new Vector3(transform.position.x + randomX, transform.position.y, transform.position.z + randomZ);
|
||
|
||
// Проверяем, находится ли точка на NavMesh
|
||
if (Physics.Raycast(walkPoint, -transform.up, 2f, whatIsGround))
|
||
walkPointSet = true;
|
||
}
|
||
|
||
private void ChasePlayer()
|
||
{
|
||
agent.SetDestination(player.position);
|
||
}
|
||
|
||
private void AttackPlayer()
|
||
{
|
||
// Враг останавливается и смотрит на игрока
|
||
agent.SetDestination(transform.position);
|
||
transform.LookAt(player);
|
||
|
||
if (!alreadyAttacked)
|
||
{
|
||
// --- Логика выстрела ---
|
||
// Создаем снаряд в точке выстрела (например, перед врагом)
|
||
//Rigidbody rb = Instantiate(projectile, transform.position + transform.forward, Quaternion.identity).GetComponent<Rigidbody>();
|
||
//rb.AddForce(transform.forward * 32f, ForceMode.Impulse);
|
||
//rb.AddForce(transform.up * 4f, ForceMode.Impulse); // Небольшой подброс для параболы
|
||
|
||
// Вместо стрельбы объектами, для простоты используем рэйкаст, как у игрока
|
||
RaycastHit hit;
|
||
if (Physics.Raycast(transform.position, transform.forward, out hit, attackRange))
|
||
{
|
||
if (hit.transform.CompareTag("Player"))
|
||
{
|
||
Debug.Log("Враг попал в игрока!");
|
||
// Наносим урон игроку
|
||
hit.transform.GetComponent<PlayerHealth>().TakeDamage(10);
|
||
}
|
||
}
|
||
// --- Конец логики выстрела ---
|
||
|
||
alreadyAttacked = true;
|
||
Invoke(nameof(ResetAttack), timeBetweenAttacks);
|
||
}
|
||
}
|
||
|
||
private void ResetAttack()
|
||
{
|
||
alreadyAttacked = false;
|
||
}
|
||
}
|