112 lines
3.1 KiB
C#
112 lines
3.1 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using UnityEngine;
|
||
|
||
public class EnemySpawner : MonoBehaviour
|
||
{
|
||
[SerializeField] private List<BezierWay> Ways;
|
||
public List<EnemyShip> EnemyPrefabs;
|
||
public bool Initialized { get; private set; }
|
||
|
||
public int MaxBudget = 1000;
|
||
public int RemainingBudget;
|
||
|
||
public event Action<EnemyShip> EnemySpawned;
|
||
|
||
[SerializeField] private float SpawnInterval = 5;
|
||
private float LastSpawnTime = 0;
|
||
|
||
public void Initialize()
|
||
{
|
||
if (Initialized) return;
|
||
|
||
if (!Validate())
|
||
{
|
||
Debug.LogError("Валидация настроек спавнера не прошла", this);
|
||
return;
|
||
}
|
||
|
||
RemainingBudget = MaxBudget;
|
||
|
||
EnemyShip.ShipReleased += EnemyShip_ShipReleased;
|
||
EnemyShip.ShipDefeated += EnemyShip_ShipReleased;
|
||
|
||
Initialized = true;
|
||
}
|
||
|
||
private void EnemyShip_ShipReleased(EnemyShip releasedShip)
|
||
{
|
||
RemainingBudget += releasedShip.SpawnCost;
|
||
}
|
||
private void OnDisable()
|
||
{
|
||
EnemyShip.ShipReleased -= EnemyShip_ShipReleased;
|
||
EnemyShip.ShipDefeated -= EnemyShip_ShipReleased;
|
||
}
|
||
|
||
public bool Validate()
|
||
{
|
||
if (EnemyPrefabs == null || EnemyPrefabs.Count == 0)
|
||
{
|
||
Debug.LogError("Не задан список врагов на спавнере", this);
|
||
return false;
|
||
}
|
||
foreach (var enemy in EnemyPrefabs)
|
||
{
|
||
if (!enemy.TryGetComponent<EnemyShip>(out _))
|
||
{
|
||
Debug.LogError($"Префаб врага {enemy.name} не содержит компонент AbstractEnemyShip");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
private void Update()
|
||
{
|
||
if (!Initialized) return;
|
||
|
||
if (CanSpawn()) Spawn();
|
||
}
|
||
|
||
|
||
private bool CanSpawn()
|
||
{
|
||
return CanSpawnByTime() && HasClearWay() && CanSpawnByBudget();
|
||
|
||
bool CanSpawnByTime() => Time.time - LastSpawnTime > SpawnInterval;
|
||
bool HasClearWay() => Ways.Any(way => !way.Busy);
|
||
bool CanSpawnByBudget() => EnemyPrefabs.Any(enemyPrefab => enemyPrefab.SpawnCost<= RemainingBudget);
|
||
}
|
||
|
||
private BezierWay GetNotBusyWay() => Ways.FirstOrDefault(way => !way.Busy);
|
||
|
||
private EnemyShip GetRandomAccessibleSheep()
|
||
{
|
||
var accessible = EnemyPrefabs.Where(e => e.GetComponent<EnemyShip>().SpawnCost <= RemainingBudget).ToList();
|
||
if (accessible.Count == 0) return null;
|
||
var randomIndex = UnityEngine.Random.Range(0, accessible.Count);
|
||
return accessible[randomIndex];
|
||
}
|
||
|
||
private void Spawn()
|
||
{
|
||
var way = GetNotBusyWay();
|
||
var sheepPrefab = GetRandomAccessibleSheep();
|
||
var go = Instantiate(sheepPrefab.gameObject, way.FirstPoint.position, Quaternion.identity);
|
||
|
||
var sheep = go.GetComponent<EnemyShip>();
|
||
|
||
sheep.AssignToWay(way);
|
||
sheep.Initialize();
|
||
|
||
EnemySpawned?.Invoke(sheep);
|
||
|
||
RemainingBudget -= sheep.SpawnCost;
|
||
|
||
LastSpawnTime = Time.time;
|
||
}
|
||
}
|