using UnityEngine; using UnityEngine.AI; public class BlindMutantAI : MonoBehaviour { private NavMeshAgent agent; private Animator animator; [Header("Настройки скорости")] public float walkSpeed = 2f; public float runSpeed = 5f; [Header("Патрулирование")] public Transform[] patrolPoints; private int currentPatrolIndex; private bool isInvestigating = false; [Header("Обнаружение игрока")] public float detectionRadius = 3.5f; // Радиус обостренных чувств (слух/запах в упор) public float losePlayerDistance = 14f; // Дистанция потери цели private Transform targetPlayer; private PlayerHealth targetPlayerHealth; [Header("Настройки атаки")] public float attackRange = 1.8f; // Дистанция ближнего боя public float attackDamage = 20f; // Урон за один удар public float attackCooldown = 1.2f; // Кулдаун между ударами private float nextAttackTime = 0f; void Start() { agent = GetComponent(); agent.speed = walkSpeed; animator = GetComponentInChildren(); // Автоматически находим игрока на сцене var playerObj = FindAnyObjectByType(); if (playerObj != null) { targetPlayerHealth = playerObj; } if (patrolPoints != null && patrolPoints.Length > 0) { GoToNextPatrolPoint(); } } void Update() { UpdateAnimator(); // 1. Поведение при активном преследовании игрока if (targetPlayer != null) { HandlePlayerChaseAndAttack(); return; } // 2. Проверка близости игрока (если подошел слишком близко — чует даже слепой) CheckProximityDetection(); // 3. Патрулирование и расследование звуков HandlePatrolAndInvestigation(); } private void UpdateAnimator() { if (animator == null) return; float currentSpeed = agent != null && agent.enabled ? agent.velocity.magnitude : 0f; animator.SetFloat("Speed", currentSpeed); } private void HandlePlayerChaseAndAttack() { if (targetPlayerHealth != null && targetPlayerHealth.IsDead) { LosePlayerTarget(); return; } float distanceToPlayer = Vector3.Distance(transform.position, targetPlayer.position); // Игрок убежал слишком далеко if (distanceToPlayer > losePlayerDistance) { LosePlayerTarget(); return; } // Игрок в зоне удара if (distanceToPlayer <= attackRange) { agent.isStopped = true; // Разворачиваемся к игроку Vector3 lookDirection = targetPlayer.position - transform.position; lookDirection.y = 0f; if (lookDirection.sqrMagnitude > 0.001f) { transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(lookDirection), Time.deltaTime * 10f); } // Наносим урон по кулдауну if (Time.time >= nextAttackTime) { nextAttackTime = Time.time + attackCooldown; if (animator != null) { animator.SetTrigger("Attack"); } if (targetPlayerHealth != null) { targetPlayerHealth.TakeDamage(attackDamage); Debug.Log($"Мутант нанес удар игроку! Урон: {attackDamage}"); } } } else { // Бежим к игроку agent.isStopped = false; agent.speed = runSpeed; agent.SetDestination(targetPlayer.position); } } private void CheckProximityDetection() { if (targetPlayerHealth == null || targetPlayerHealth.IsDead) return; float distance = Vector3.Distance(transform.position, targetPlayerHealth.transform.position); if (distance <= detectionRadius) { EngagePlayer(targetPlayerHealth.transform); } } private void HandlePatrolAndInvestigation() { if (!agent.pathPending && agent.remainingDistance < 0.5f) { if (isInvestigating) { isInvestigating = false; agent.speed = walkSpeed; if (patrolPoints != null && patrolPoints.Length > 0) { GoToNextPatrolPoint(); } } else if (patrolPoints != null && patrolPoints.Length > 0) { GoToNextPatrolPoint(); } } } private void EngagePlayer(Transform playerTransform) { targetPlayer = playerTransform; if (targetPlayerHealth == null) { targetPlayerHealth = playerTransform.GetComponent(); } isInvestigating = false; agent.isStopped = false; agent.speed = runSpeed; agent.SetDestination(targetPlayer.position); Debug.Log("Мутант обнаружил игрока и начинает атаку!"); } private void LosePlayerTarget() { targetPlayer = null; agent.isStopped = false; agent.speed = walkSpeed; isInvestigating = false; if (patrolPoints != null && patrolPoints.Length > 0) { GoToNextPatrolPoint(); } Debug.Log("Мутант потерял игрока и возвращается к патрулированию."); } private void GoToNextPatrolPoint() { if (patrolPoints == null || patrolPoints.Length == 0) return; agent.destination = patrolPoints[currentPatrolIndex].position; currentPatrolIndex = (currentPatrolIndex + 1) % patrolPoints.Length; } public void HearSound(Vector3 soundPosition) { // Если уже бьем игрока в упор, не отвлекаемся на случайный шум вдалеке if (targetPlayer != null && Vector3.Distance(transform.position, targetPlayer.position) <= attackRange) { return; } isInvestigating = true; agent.isStopped = false; agent.speed = runSpeed; agent.SetDestination(soundPosition); } public void OnDamagedByPlayer(Transform player) { if (animator != null) { animator.SetTrigger("GetHit"); } EngagePlayer(player); } private void OnDrawGizmosSelected() { // Радиус ближнего обнаружения Gizmos.color = Color.yellow; Gizmos.DrawWireSphere(transform.position, detectionRadius); // Радиус атаки Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position, attackRange); } }