202 lines
8.0 KiB
C#
202 lines
8.0 KiB
C#
using UnityEngine;
|
||
using UnityEngine.AI;
|
||
using UnityEngine.SceneManagement; // Для перезапуска сцены при смерти
|
||
|
||
public class EnemyAI : MonoBehaviour
|
||
{
|
||
[Header("Настройки врага")]
|
||
public float detectionRange = 10f; // Радиус обнаружения игрока
|
||
public float attackRange = 2f; // Дистанция атаки (немедленная смерть)
|
||
public float patrolSpeed = 5f; // Скорость патрулирования
|
||
public float chaseSpeed = 9f; // Скорость преследования
|
||
|
||
[Header("Патрульные точки")]
|
||
public Transform[] patrolPoints; // Точки для патрулирования
|
||
|
||
[Header("Звуковые эффекты")]
|
||
public AudioClip movementSound; // Звук перемещения (зацикленный)
|
||
public AudioClip detectionSound; // Звук обнаружения игрока
|
||
public AudioClip killSound; // Звук убийства игрока
|
||
|
||
private Transform player; // Ссылка на игрока
|
||
private NavMeshAgent agent; // Компонент NavMeshAgent
|
||
private Animator animator; // Компонент Animator
|
||
private AudioSource audioSource; // Компонент AudioSource
|
||
private int currentPatrolIndex; // Индекс текущей точки патруля
|
||
private enum EnemyState { Patrol, Chase, Attack } // Состояния врага
|
||
private EnemyState currentState = EnemyState.Patrol; // Текущее состояние
|
||
private bool hasKilledPlayer = false; // Флаг для предотвращения повторного воспроизведения звука убийства
|
||
|
||
void Start()
|
||
{
|
||
// Находим компоненты
|
||
agent = GetComponent<NavMeshAgent>();
|
||
// animator = GetComponent<Animator>();
|
||
audioSource = GetComponent<AudioSource>();
|
||
player = GameObject.FindGameObjectWithTag("Player").transform; // Убедись, что у игрока есть тег "Player"
|
||
|
||
// Проверка наличия AudioSource
|
||
if (audioSource == null)
|
||
{
|
||
audioSource = gameObject.AddComponent<AudioSource>();
|
||
Debug.LogWarning("AudioSource не был найден, добавлен автоматически.");
|
||
}
|
||
|
||
// Настройка начальных параметров AudioSource
|
||
audioSource.playOnAwake = false;
|
||
audioSource.loop = true; // Зацикливание для звука перемещения
|
||
if (movementSound != null)
|
||
{
|
||
audioSource.clip = movementSound;
|
||
audioSource.Play(); // Начать воспроизведение звука перемещения
|
||
}
|
||
|
||
// Настройка начальных параметров NavMeshAgent
|
||
agent.speed = patrolSpeed;
|
||
|
||
// Устанавливаем начальное состояние
|
||
if (patrolPoints.Length > 0)
|
||
{
|
||
agent.SetDestination(patrolPoints[currentPatrolIndex].position);
|
||
}
|
||
}
|
||
|
||
void Update()
|
||
{
|
||
// Проверяем дистанцию до игрока
|
||
float distanceToPlayer = Vector3.Distance(transform.position, player.position);
|
||
|
||
// Определяем состояние врага
|
||
if (distanceToPlayer <= attackRange)
|
||
{
|
||
if (currentState != EnemyState.Attack)
|
||
{
|
||
// Останавливаем все текущие звуки при входе в состояние атаки
|
||
if (audioSource.isPlaying)
|
||
{
|
||
audioSource.Stop();
|
||
}
|
||
}
|
||
currentState = EnemyState.Attack;
|
||
}
|
||
else if (distanceToPlayer <= detectionRange)
|
||
{
|
||
if (currentState != EnemyState.Chase)
|
||
{
|
||
|
||
if (detectionSound != null && audioSource.clip != detectionSound)
|
||
{
|
||
audioSource.Stop(); // Останавливаем текущий звук
|
||
audioSource.loop = true; // Зацикливание для звука преследования
|
||
audioSource.clip = detectionSound;
|
||
audioSource.Play(); // Начать воспроизведение звука преследования
|
||
}
|
||
}
|
||
currentState = EnemyState.Chase;
|
||
|
||
}
|
||
else
|
||
{
|
||
if (currentState != EnemyState.Patrol)
|
||
{
|
||
// Останавливаем звук преследования и возвращаемся к звуку перемещения
|
||
if (audioSource.clip == detectionSound)
|
||
{
|
||
audioSource.Stop();
|
||
if (movementSound != null)
|
||
{
|
||
audioSource.clip = movementSound;
|
||
audioSource.Play();
|
||
}
|
||
}
|
||
}
|
||
currentState = EnemyState.Patrol;
|
||
}
|
||
|
||
// Выполняем действия в зависимости от состояния
|
||
switch (currentState)
|
||
{
|
||
case EnemyState.Patrol:
|
||
Patrol();
|
||
break;
|
||
case EnemyState.Chase:
|
||
ChasePlayer();
|
||
break;
|
||
case EnemyState.Attack:
|
||
KillPlayer();
|
||
break;
|
||
}
|
||
|
||
UpdateMovementSound();
|
||
}
|
||
|
||
void Patrol()
|
||
{
|
||
agent.speed = patrolSpeed; // Устанавливаем скорость патрулирования
|
||
|
||
// Если враг достиг точки патруля, выбираем следующую
|
||
if (!agent.pathPending && agent.remainingDistance < 0.5f)
|
||
{
|
||
currentPatrolIndex = (currentPatrolIndex + 1) % patrolPoints.Length;
|
||
agent.SetDestination(patrolPoints[currentPatrolIndex].position);
|
||
}
|
||
}
|
||
|
||
void ChasePlayer()
|
||
{
|
||
agent.speed = chaseSpeed; // Устанавливаем скорость преследования
|
||
agent.SetDestination(player.position); // Идём к игроку
|
||
}
|
||
|
||
void KillPlayer()
|
||
{
|
||
agent.SetDestination(transform.position); // Останавливаем движение
|
||
|
||
// Воспроизводим звук убийства только один раз
|
||
if (killSound != null && !hasKilledPlayer)
|
||
{
|
||
audioSource.PlayOneShot(killSound);
|
||
hasKilledPlayer = true; // Устанавливаем флаг
|
||
}
|
||
|
||
// Немедленная смерть игрока
|
||
Debug.Log("Игрок убит!");
|
||
// Перезапускаем сцену (или показываем экран смерти)
|
||
GameUIManager uiManager = FindObjectOfType<GameUIManager>();
|
||
if (uiManager != null)
|
||
{
|
||
uiManager.ShowDeathScreen();
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("GameUIManager не найден в сцене!");
|
||
}
|
||
}
|
||
|
||
void UpdateMovementSound()
|
||
{
|
||
// Включаем/выключаем звук перемещения только в состоянии Patrol
|
||
if (movementSound != null && audioSource != null && audioSource.clip == movementSound && currentState == EnemyState.Patrol)
|
||
{
|
||
if (agent.velocity.magnitude > 0.1f && !audioSource.isPlaying)
|
||
{
|
||
audioSource.Play();
|
||
}
|
||
else if (agent.velocity.magnitude <= 0.1f && audioSource.isPlaying)
|
||
{
|
||
audioSource.Stop();
|
||
}
|
||
}
|
||
}
|
||
|
||
void OnDrawGizmosSelected()
|
||
{
|
||
// Радиус обнаружения
|
||
Gizmos.color = Color.yellow;
|
||
Gizmos.DrawWireSphere(transform.position, detectionRange);
|
||
|
||
// Радиус атаки
|
||
Gizmos.color = Color.red;
|
||
Gizmos.DrawWireSphere(transform.position, attackRange);
|
||
}
|
||
} |