Загрузка данных
using UnityEngine;
using UnityEngine.AI;
public class MonsterAI : MonoBehaviour
{
[Header("Настройки зрения")]
public float viewDistance = 20f;
[Range(0, 180)] public float viewAngle = 90f;
public float looseDistance = 25f;
[Header("Настройки патрулирования")]
public float patrolSpeed = 2f; // Скорость когда просто ходит по лесу
public float chaseSpeed = 5f; // Скорость когда бежит за Олегом
public float patrolRadius = 30f; // Радиус в котором он выбирает случайные точки для прогулки
private Transform playerTransform;
private NavMeshAgent agent;
private Animator animator;
private bool isChasing = false;
private Vector3 patrolTarget;
void Start()
{
agent = GetComponent<NavMeshAgent>();
animator = GetComponent<Animator>();
GameObject playerObj = GameObject.FindGameObjectWithTag("Player");
if (playerObj != null) playerTransform = playerObj.transform;
// Выбираем первую случайную точку для прогулки при старте
SetNewRandomDestination();
}
void Update()
{
if (playerTransform == null) return;
bool canSee = CanSeePlayer();
if (canSee)
{
isChasing = true; // Заметил Олега!
}
else
{
float distanceToPlayer = Vector3.Distance(transform.position, playerTransform.position);
if (distanceToPlayer > looseDistance)
{
isChasing = false; // Потерял Олега
}
}
// УПРАВЛЕНИЕ ДВИЖЕНИЕМ И СКОРОСТЬЮ
if (agent.isActiveAndEnabled && agent.isOnNavMesh)
{
if (isChasing)
{
agent.isStopped = false;
agent.speed = chaseSpeed; // Включаем бег
agent.SetDestination(playerTransform.position); // Преследуем
}
else
{
agent.isStopped = false;
agent.speed = patrolSpeed; // Включаем медленный шаг/прогулку
// Если монстр дошел до своей точки патрулирования или уперся в тупик — выбираем новую точку
if (!agent.pathPending && agent.remainingDistance < 1.5f)
{
SetNewRandomDestination();
}
}
}
if (animator != null)
{
bool isMoving = agent.velocity.magnitude > 0.1f;
animator.SetBool("IsMoving", isMoving);
}
}
// Ищет случайную валидную точку на синей сетке NavMesh вокруг монстра
void SetNewRandomDestination()
{
Vector3 randomDirection = Random.insideUnitSphere * patrolRadius;
randomDirection += transform.position;
NavMeshHit navHit;
// Проверяем, существует ли навигационная сетка в выбранной случайной точке
if (NavMesh.SamplePosition(randomDirection, out navHit, patrolRadius, -1))
{
patrolTarget = navHit.position;
agent.SetDestination(padlockTarget ?? patrolTarget);
}
}
bool CanSeePlayer()
{
float distance = Vector3.Distance(transform.position, playerTransform.position);
if (distance <= viewDistance)
{
Vector3 directionToPlayer = (playerTransform.position - transform.position).normalized;
float angle = Vector3.Angle(transform.forward, directionToPlayer);
if (angle < viewAngle / 2f)
{
RaycastHit hit;
Vector3 startPos = transform.position + Vector3.up;
Vector3 targetPos = playerTransform.position + Vector3.up;
if (Physics.Raycast(startPos, (targetPos - startPos).normalized, out hit, viewDistance))
{
if (hit.transform.CompareTag("Player")) return true;
}
}
}
return false;
}
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position, viewDistance);
Vector3 leftBoundary = Quaternion.Euler(0, -viewAngle / 2f, 0) * transform.forward;
Vector3 rightBoundary = Quaternion.Euler(0, viewAngle / 2f, 0) * transform.forward;
Gizmos.color = Color.yellow;
Gizmos.DrawLine(transform.position, transform.position + leftBoundary * viewDistance);
Gizmos.DrawLine(transform.position, transform.position + rightBoundary * viewDistance);
}
}