Загрузка данных


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);
    }
}