using System.Collections.Generic; using UnityEngine; public class EnemySpawner : MonoBehaviour { [Header("Spawn Configuration")] [SerializeField] private Enemy _enemyPrefab; [SerializeField] private int _maxAliveCount = 3; [SerializeField] private float _spawnInterval = 2f; [SerializeField] private float _initialDelay = 0f; [Header("Spawn Position")] [SerializeField] private Transform[] _spawnPoints; [SerializeField] private float _spawnRadius = 0f; [SerializeField] private Transform _enemyParent; [Header("Behavior")] [SerializeField] private bool _spawnOnStart = true; [SerializeField] private bool _respawnOnDeath = true; [SerializeField] private int _totalSpawnLimit = 0; private readonly List _aliveEnemies = new(); private float _nextSpawnTime; private int _totalSpawned; private bool _active; private void Start() { if (_spawnOnStart) BeginSpawning(); } public void BeginSpawning() { _active = true; _nextSpawnTime = Time.time + _initialDelay; } public void StopSpawning() => _active = false; public void ResetSpawner() { for (int i = _aliveEnemies.Count - 1; i >= 0; i--) { if (_aliveEnemies[i] != null) Destroy(_aliveEnemies[i].gameObject); } _aliveEnemies.Clear(); _totalSpawned = 0; _nextSpawnTime = Time.time + _initialDelay; } private void Update() { if (!_active) return; _aliveEnemies.RemoveAll(e => e == null); if (!_respawnOnDeath && _aliveEnemies.Count == 0 && _totalSpawned > 0) return; if (_totalSpawnLimit > 0 && _totalSpawned >= _totalSpawnLimit) return; if (_aliveEnemies.Count >= _maxAliveCount) return; if (Time.time < _nextSpawnTime) return; if (_enemyPrefab == null) return; SpawnOne(); _nextSpawnTime = Time.time + _spawnInterval; } public Enemy SpawnOne() { if (_enemyPrefab == null) return null; Vector3 spawnPos = GetSpawnPosition(); Enemy enemy = Instantiate(_enemyPrefab, spawnPos, Quaternion.identity, _enemyParent); _aliveEnemies.Add(enemy); _totalSpawned++; return enemy; } private Vector3 GetSpawnPosition() { Vector3 basePos; if (_spawnPoints != null && _spawnPoints.Length > 0) { Transform pick = _spawnPoints[Random.Range(0, _spawnPoints.Length)]; basePos = pick != null ? pick.position : transform.position; } else { basePos = transform.position; } if (_spawnRadius > 0f) { Vector2 offset = Random.insideUnitCircle * _spawnRadius; basePos.x += offset.x; basePos.y += offset.y; } return basePos; } private void OnDrawGizmosSelected() { Color pointColor = Color.cyan; Color radiusColor = new Color(0f, 1f, 1f, 0.25f); if (_spawnPoints != null && _spawnPoints.Length > 0) { foreach (var p in _spawnPoints) { if (p == null) continue; Gizmos.color = pointColor; Gizmos.DrawWireSphere(p.position, 0.3f); if (_spawnRadius > 0f) { Gizmos.color = radiusColor; Gizmos.DrawWireSphere(p.position, _spawnRadius); } } } else { Gizmos.color = pointColor; Gizmos.DrawWireSphere(transform.position, 0.3f); if (_spawnRadius > 0f) { Gizmos.color = radiusColor; Gizmos.DrawWireSphere(transform.position, _spawnRadius); } } } }