Add EnemyWave and EnemyWavesManager classes; implement enemy spawning system for wave-based gameplay

This commit is contained in:
2025-07-12 02:34:15 +02:00
parent ad02e07a87
commit ced721f1ad
5 changed files with 250 additions and 326 deletions

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using Sirenix.Serialization;
using UnityEngine;
namespace Data
{
[CreateAssetMenu(menuName = "Game/Wave")]
public class EnemyWave : ScriptableObject
{
[TableList]
[OdinSerialize] public List<EnemySpawnInfo> spawns = new();
}
[Serializable]
public class EnemySpawnInfo
{
[HorizontalGroup("Row", width: 80)]
[OdinSerialize, PreviewField(80)] public GameObject enemyPrefab;
[HorizontalGroup("Row")]
[OdinSerialize] public int count = 1;
[HorizontalGroup("Row")] [OdinSerialize]
public float spawnInterval = 0.5f;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 998e0b91932048b1b2abcfcf4936b508
timeCreated: 1752279009

View File

@@ -0,0 +1,68 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Data;
using KBCore.Refs;
using Sirenix.OdinInspector;
using Sirenix.Serialization;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Systems
{
public class EnemyWavesManager : MonoBehaviour
{
[OdinSerialize, ListDrawerSettings(NumberOfItemsPerPage = 20), SerializeField]
private List<EnemyWave> waves = new();
[OdinSerialize, SerializeField] private Transform[] spawnPoints;
private Coroutine spawnCoroutine;
private List<GameObject> aliveEnemies = new();
[Self, SerializeField] private GameManager gameManager;
private void OnEnable()
{
gameManager.OnRoundStart += StartWave;
gameManager.OnRoundEnd += EndWave;
}
private void OnDisable()
{
gameManager.OnRoundStart -= StartWave;
gameManager.OnRoundEnd -= EndWave;
}
private void StartWave(int round)
{
if (spawnCoroutine != null) StopCoroutine(spawnCoroutine);
if (round - 1 < waves.Count) spawnCoroutine = StartCoroutine(SpawnWave(waves[round - 1]));
}
private void EndWave(int round)
{
foreach (var enemy in aliveEnemies)
{
if (!enemy) continue;
Destroy(enemy);
}
aliveEnemies.Clear();
if (spawnCoroutine != null) StopCoroutine(spawnCoroutine);
}
private IEnumerator SpawnWave(EnemyWave wave)
{
foreach (var spawn in wave.spawns)
{
for (var i = 0; i < spawn.count; i++)
{
var spawnPoint = spawnPoints[Random.Range(0, spawnPoints.Length)];
var enemy = Instantiate(spawn.enemyPrefab, spawnPoint.position, Quaternion.identity);
aliveEnemies.Add(enemy);
yield return new WaitForSeconds(spawn.spawnInterval);
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a52015481bb34a49b69096e5eff49e42
timeCreated: 1752279160