Unity_1lab/1 laba/Assets/Scripts/EnemyAI.cs

197 lines
8.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 hasDetectedPlayer = false; // Флаг для предотвращения повторного воспроизведения звука обнаружения
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)
{
currentState = EnemyState.Attack;
}
else if (distanceToPlayer <= detectionRange)
{
if (currentState != EnemyState.Chase && !hasDetectedPlayer)
{
// Воспроизводим звук обнаружения один раз
if (detectionSound != null)
{
audioSource.PlayOneShot(detectionSound);
hasDetectedPlayer = true; // Устанавливаем флаг
}
}
currentState = EnemyState.Chase;
hasKilledPlayer = false; // Сбрасываем флаг убийства, если игрок вышел из зоны атаки
}
else
{
currentState = EnemyState.Patrol;
hasDetectedPlayer = false; // Сбрасываем флаг, если игрок вне зоны
hasKilledPlayer = false; // Сбрасываем флаг убийства
}
// Выполняем действия в зависимости от состояния
switch (currentState)
{
case EnemyState.Patrol:
Patrol();
break;
case EnemyState.Chase:
ChasePlayer();
break;
case EnemyState.Attack:
KillPlayer();
break;
}
// Обновляем звук перемещения
UpdateMovementSound();
// Обновляем анимации
// UpdateAnimations();
}
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()
{
// Включаем/выключаем звук перемещения в зависимости от движения
if (movementSound != null && audioSource != null)
{
if (agent.velocity.magnitude > 0.1f && !audioSource.isPlaying)
{
audioSource.clip = movementSound;
audioSource.Play();
}
else if (agent.velocity.magnitude <= 0.1f && audioSource.isPlaying && audioSource.clip == movementSound)
{
audioSource.Stop();
}
}
}
/*
void UpdateAnimations()
{
// Предполагается, что в Animator есть параметры "IsWalking" и "IsAttacking"
animator.SetBool("IsWalking", currentState == EnemyState.Patrol || currentState == EnemyState.Chase);
animator.SetBool("IsAttacking", currentState == EnemyState.Attack);
}
*/
// Визуализация радиусов в редакторе (для удобства настройки)
void OnDrawGizmosSelected()
{
// Радиус обнаружения
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(transform.position, detectionRange);
// Радиус атаки
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, attackRange);
}
}