Finished group spawn

Created Serializable class GroupList in WaveConfig.cs to contain multiple enemy types per group
This commit is contained in:
Ader Alisma 01 2023-10-18 20:30:31 -04:00
parent b076430b34
commit af66cd5cfa
5 changed files with 117 additions and 28 deletions

View File

@ -10,12 +10,14 @@ namespace GatherAndDefend.LevelEditor
{ {
EditorGUILayout.HelpBox(@"How to use : EditorGUILayout.HelpBox(@"How to use :
- ConstantSpawn: Drag the chosen Enemy and insert the number to make in Count - ConstantSpawn: Drag the chosen Enemy and insert the number to make in Count
- GroupSpawn: Each group contains enemies, and the time to trigger in float format for minutes.
- GameDuration : Duration of the game, in minutes - GameDuration : Duration of the game, in minutes
- Usage : Drop this config into a level - Usage : Drop this config into a level
- Creation interval is determined by the game duration and the number of enemies to create - The creation interval is determined by the game duration and the number of enemies to create
Important consideration : Important consideration :
- You must assign at least 1 enemy of Count of at least 1 to play.", MessageType.None); - You must assign at least 1 enemy of Count of at least 1 to play.
- GameDuration cannot be 0.", MessageType.None);
base.OnInspectorGUI(); base.OnInspectorGUI();
} }
} }

View File

@ -1,6 +1,11 @@
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
[System.Serializable]
public class GroupList
{
public List<EnemyType> groupSpawn;
public float triggerTime;
}
[CreateAssetMenu(menuName = "Gather And Defend/Levels/WaveConfig")] [CreateAssetMenu(menuName = "Gather And Defend/Levels/WaveConfig")]
public class WaveConfig : ScriptableObject public class WaveConfig : ScriptableObject
{ {
@ -8,9 +13,9 @@ public class WaveConfig : ScriptableObject
[SerializeField] [SerializeField]
private List<EnemyType> _constantSpawn = new List<EnemyType>(); private List<EnemyType> _constantSpawn = new List<EnemyType>();
[SerializeField] [SerializeField]
private List<EnemyType> _groupSpawn = new List<EnemyType>(); //TODO: Turn into List of list later on private List<GroupList> _nestedGroupSpawn = new List<GroupList>();
[SerializeField] [SerializeField]
private float _gameDuration = 0; private float _gameDuration = 1;
private float _enemySpawndOnStart = 0; private float _enemySpawndOnStart = 0;
private int _enemySum = 0; private int _enemySum = 0;
public List<EnemyType> ConstantSpawn public List<EnemyType> ConstantSpawn
@ -20,17 +25,35 @@ public class WaveConfig : ScriptableObject
return _constantSpawn; return _constantSpawn;
} }
} }
/**
* Contains every list of enemy groups
*/
public List<GroupList> NestedGroupSpawn
{
get
{
return _nestedGroupSpawn;
}
}
public float GetInterval() public float GetInterval()
{ {
float interval = _gameDuration * 60.0f / (_enemySum > 0 ? _enemySum.ToFloat() : SumCount()) ; float interval = _gameDuration * 60.0f / (_enemySum > 0 ? _enemySum.ToFloat() : SumCount());
return interval; return interval;
} }
/**
* Returns the updated game interval after adjusting to enemies spawned at the start
*/
public float GetUpdatedInterval() public float GetUpdatedInterval()
{ {
_enemySpawndOnStart++; _enemySpawndOnStart++;
float interval = Mathf.Max(_gameDuration * 60.0f / (_enemySum - _enemySpawndOnStart).ToFloat(), 0); float interval = Mathf.Max(_gameDuration * 60.0f / (_enemySum - _enemySpawndOnStart).ToFloat(), 0);
return interval; return interval;
} }
/**
* Returns a random enemy among the constantSpawn list
*/
public EnemyType GetRandomSpawn() public EnemyType GetRandomSpawn()
{ {
if (_constantSpawn.Count == 1) if (_constantSpawn.Count == 1)
@ -39,6 +62,10 @@ public class WaveConfig : ScriptableObject
} }
return _constantSpawn[Random.Range(0, _constantSpawn.Count - 1)]; return _constantSpawn[Random.Range(0, _constantSpawn.Count - 1)];
} }
/**
* Returns the count of enemies to spawn
*/
private float SumCount() private float SumCount()
{ {
foreach (EnemyType enemy in _constantSpawn) foreach (EnemyType enemy in _constantSpawn)
@ -47,10 +74,4 @@ public class WaveConfig : ScriptableObject
} }
return _enemySum.ToFloat(); return _enemySum.ToFloat();
} }
public List<EnemyType> getGroupList()
{
return _groupSpawn;
}
} }

View File

@ -1,26 +1,36 @@
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using System;
public class WaveObserver : Singleton<WaveObserver> public class WaveObserver : Singleton<WaveObserver>
{ {
private List<SpawnerTile> _subjects = new List<SpawnerTile>(); private List<SpawnerTile> _subjects = new List<SpawnerTile>();
private List<float> _aliveEnemyCount = new List<float>(); private List<float> _aliveEnemyCount = new List<float>();
private List<int> _copyConstantSpawn; private List<int> _copyConstantSpawn;
private List<GroupList> _copyGroupSpawn;
private List<float> _groupSpawnTimers;
private WaveConfig _levelConfig; private WaveConfig _levelConfig;
private const int MAXTOUGHNESS = 10; private const int MAXTOUGHNESS = 10;
private int _spawnerTiming = 0; private int _spawnerTiming = 0;
private List<int> _intervalTiming = new List<int>(); private List<int> _intervalTiming = new List<int>();
private bool _once = true;
private int _currentGroupIndex = 0;
public WaveConfig LevelConfig public WaveConfig LevelConfig
{ {
set set
{ {
_levelConfig = value; _levelConfig = value;
_copyConstantSpawn = new List<int>(); _copyConstantSpawn = new List<int>();
_copyGroupSpawn = new List<GroupList>();
_groupSpawnTimers = new List<float>();
foreach (EnemyType enemy in _levelConfig.ConstantSpawn) foreach (EnemyType enemy in _levelConfig.ConstantSpawn)
{ {
_copyConstantSpawn.Add(enemy.Count); _copyConstantSpawn.Add(enemy.Count);
} }
for (int index = 0; index < _levelConfig.NestedGroupSpawn.Count; index++)
{
_copyGroupSpawn.Add(_levelConfig.NestedGroupSpawn[index]);
_groupSpawnTimers.Add(_levelConfig.NestedGroupSpawn[index].triggerTime);
}
} }
} }
@ -35,6 +45,12 @@ public class WaveObserver : Singleton<WaveObserver>
_subjects.Add(spawnerSubject); _subjects.Add(spawnerSubject);
_aliveEnemyCount.Add(0); _aliveEnemyCount.Add(0);
_intervalTiming.Add(++_spawnerTiming); _intervalTiming.Add(++_spawnerTiming);
// Ensures that only one spawner keeps track of the grouped spawn timer.
if (_once)
{
_once = false;
spawnerSubject.GroupSpawnTimers = _groupSpawnTimers;
}
} }
/** /**
@ -139,4 +155,21 @@ public class WaveObserver : Singleton<WaveObserver>
spawnerTile.ChangeSpawnSpeed(_levelConfig.GetInterval() * _intervalTiming[index]); spawnerTile.ChangeSpawnSpeed(_levelConfig.GetInterval() * _intervalTiming[index]);
_intervalTiming.Remove(index); _intervalTiming.Remove(index);
} }
/**
* Called when it is time to spawn a group
* Assigns a random element of the group to a random spawner
*/
public void NotifyGroupSpawn()
{
System.Random rand = new System.Random();
foreach (EnemyType groupEnemy in _copyGroupSpawn[_currentGroupIndex].groupSpawn)
{
for (int i = 0; i < groupEnemy.Count; i++)
{
_subjects[rand.Next(_subjects.Count)].TriggerSpawn(groupEnemy.GetEnemyObject());
}
}
_currentGroupIndex++;
}
} }

View File

@ -16,6 +16,14 @@ public class SpawnerTile : LevelTile
private WaveObserver _observer; private WaveObserver _observer;
private bool _stopped = false; private bool _stopped = false;
private bool _cooldownEnded = false; private bool _cooldownEnded = false;
private List<float> _groupSpawnTimers = new List<float>();
public List<float> GroupSpawnTimers
{
set
{
_groupSpawnTimers = value;
}
}
public override void LevelStart() public override void LevelStart()
@ -24,7 +32,7 @@ public class SpawnerTile : LevelTile
_observer.Attach(this); _observer.Attach(this);
if (_spawnOnStart && _lifetime <= 0) if (_spawnOnStart && _lifetime <= 0)
{ {
_prefab.Create(Position, parent: LevelManager.Instance.LevelTransform); TriggerSpawn(_prefab);
_observer.NotifyOnStart(this); _observer.NotifyOnStart(this);
} }
} }
@ -36,6 +44,14 @@ public class SpawnerTile : LevelTile
{ {
_spawnCounter += Time.deltaTime; _spawnCounter += Time.deltaTime;
} }
if (_groupSpawnTimers.Count > 0)
{
if (_lifetime / 60 > _groupSpawnTimers[0])
{
_groupSpawnTimers.RemoveAt(0);
_observer.NotifyGroupSpawn();
}
}
if (_spawnCounter < _spawnSpeed) return; if (_spawnCounter < _spawnSpeed) return;
_spawnCounter = 0; _spawnCounter = 0;
@ -45,7 +61,7 @@ public class SpawnerTile : LevelTile
_cooldownEnded = true; _cooldownEnded = true;
return; return;
} }
_prefab.Create(Position, parent: LevelManager.Instance.LevelTransform); TriggerSpawn(_prefab);
_observer.NotifySpawned(this); _observer.NotifySpawned(this);
} }
public override bool Equals(ILevelObject other) public override bool Equals(ILevelObject other)
@ -110,4 +126,13 @@ public class SpawnerTile : LevelTile
{ {
_spawnSpeed = value; _spawnSpeed = value;
} }
/**
* Instantly spawns an enemy.
* Used for GroupSpawn
*/
public void TriggerSpawn(GameObject enemy)
{
enemy.Create(Position, parent: LevelManager.Instance.LevelTransform);
}
} }

View File

@ -15,9 +15,17 @@ MonoBehaviour:
_constantSpawn: _constantSpawn:
- _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3} - _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3}
_count: 5 _count: 5
_groupSpawn: _nestedGroupSpawn:
- _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3} - groupSpawn:
_count: 3 - _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3}
- _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3} _count: 3
_count: 1 - _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3}
_gameDuration: 1 _count: 1
triggerTime: 0.5
- groupSpawn:
- _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3}
_count: 1
- _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3}
_count: 2
triggerTime: 0
_gameDuration2: 5