Загрузка данных
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;
}
}