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


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
//1. раз в определенное время враг телепортируется в место которое не видно игроку
// рядом с игроком
//2. когда мы посмотрим прямо на врага, он заагрится
//3. через некоторое время он за нами начинает бежать
//4. как спастись......?

public class EnemyController : MonoBehaviour
{
    [Header("Components")]
    [SerializeField] private Transform playerTR;
    [SerializeField] private Camera cam;
    [SerializeField] private Transform enemyHead;
    [Header("Spawn Logic")]
    [SerializeField] private float minSpawnCooldown; //время которое он ждёт
    [SerializeField] private float maxSpawnCooldown;
    [SerializeField] private float minSpawnDistance;
    [SerializeField] private float maxSpawnDistance; //viewDistance
    [SerializeField] private float frontSpawnDistance; //дистанция спавна перед нами
    [Header("Chase Logic")]
    [SerializeField] private float chaseCooldown; //время за которое он нас потеряет из виду
    [SerializeField] private float spottingMargin; //область вокруг врага, если на неё посмотреть он агрица
    [SerializeField] private int spawnTriesLimit = 50; //лимит попыток для спавна врага
    [SerializeField] private float chaseStartCooldown = 2; //время через которое он начинает бежать
    [Header("Sounds")]
    [SerializeField] private AudioSource audioSource;
    [SerializeField] private AudioClip spottingSound;    //когда заметил
    //[SerializeField] private AudioClip chaseEndedSound; //когда угомонился
    [SerializeField] private AudioClip chaseLoopSound; //зацикленный звук погони
    //[SerializeField] private AudioClip[] chaseSounds; //рандомные звуки погони
    //[SerializeField] private AudioClip[] idleSounds; //рандомные звуки когда он стоит
    
    
    private Transform _camTR;
    private float _spawnTimer;
    private float _chaseStartTimer; //таймер начала погони
    private float _loseSightTimer;  //таймер потери нас из виду
    private Vector3 _enemySpawnPoint;
    private NavMeshAgent _agent;

    private int _spawnTries;
    private bool _isAngry;
    
    //limit popitok
    
    // Start is called before the first frame update
    void Start()
    {
        _camTR = cam.GetComponent<Transform>();
        _agent = GetComponent<NavMeshAgent>();
    }

    // Update is called once per frame
    void Update()
    {
        Vector3 playerDir = _camTR.forward;
        Vector3 playerToPointDir = (transform.position - _camTR.position).normalized;
        float dotProduct = Vector3.Dot(playerDir, playerToPointDir);
        if (!_isAngry)
        {
            if (dotProduct > spottingMargin)
            {
                Vector3 dir = (playerTR.position - enemyHead.position).normalized;
                if (Physics.Raycast(enemyHead.position, dir, out var hit, maxSpawnDistance))
                {
                    if (hit.collider.CompareTag("Player"))
                    {
                        _isAngry = true;
                        Debug.Log("Я ЗЛОЙ ЖЕСС");
                        _chaseStartTimer = chaseStartCooldown;
                        _loseSightTimer = chaseCooldown;
                        //sound
                    }
                }
            }
        }
        else
        {
            if (_chaseStartTimer > 0)
            {
                _chaseStartTimer -= Time.deltaTime;
            }

            if (_chaseStartTimer <= 0)
            {
                //ПОГОНЯ
                _agent.SetDestination(playerTR.position);
                Vector3 dir = (playerTR.position - enemyHead.position).normalized;
                if (Physics.Raycast(enemyHead.position,dir, out var hit, maxSpawnDistance))
                {
                    if (!hit.collider.CompareTag("Player"))
                    {
                        _loseSightTimer -= Time.deltaTime;
                    }
                    else
                    {
                        _loseSightTimer = chaseCooldown;
                    }
                }
                if (_loseSightTimer <= 0)
                {
                    _isAngry = false;
                    _chaseStartTimer = chaseStartCooldown;
                }
            }
        }
        
        if (_spawnTimer <= 0)
        {
            _spawnTimer = Random.Range(minSpawnCooldown, maxSpawnCooldown);
            
            if (dotProduct > 0 || _isAngry)
            {
                return;
            }
            
            FindPoint(playerTR.position);
            transform.position = _enemySpawnPoint;
        }
        if (_spawnTimer > 0)
        {
            _spawnTimer -= Time.deltaTime;
        }
        
    }

    private void FindPoint(Vector3 playerPos)
    {
        _spawnTries++;
        if (_spawnTries > spawnTriesLimit)
        {
            _spawnTries = 0;
            return;
            //zapret
        }
        Vector3 playerDir = _camTR.forward;

        Vector3 randomPoint = Random.insideUnitCircle.normalized * Random.Range(minSpawnDistance, maxSpawnDistance);
        Vector3 randomPointPlayer = playerPos + new Vector3(randomPoint.x,0,randomPoint.y); 
        
        Vector3 playerToPointDir = (randomPointPlayer - _camTR.position).normalized;

        if ((playerPos - randomPointPlayer).magnitude < frontSpawnDistance)
        {
            float dotProduct = Vector3.Dot(playerDir, playerToPointDir); //-1 -- 1
            if (dotProduct > 0)
            {
                //плохая точка
                FindPoint(playerPos);
                return;
            }
        }
        

        if (!NavMesh.SamplePosition(randomPointPlayer, out NavMeshHit hit, 1f, NavMesh.AllAreas))
        {
            FindPoint(playerPos);
            return;
        }
        _spawnTries = 0;
        _enemySpawnPoint = randomPointPlayer;
    }
}