Pull request #46: WaveGroup
Merge in CGD/gather-and-defend from feature/waveGroup to main * commit 'c57417a583816bcd1c3d33a8422c5c91275d0377': PR corrections Updated wave config Finished group spawn Start group spawn Finished group spawn Start group spawn
This commit is contained in:
commit
8e767297e6
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,7 +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 float _gameDuration = 0;
|
private List<GroupList> _nestedGroupSpawn = new List<GroupList>();
|
||||||
|
[SerializeField]
|
||||||
|
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
|
||||||
@ -18,17 +25,37 @@ public class WaveConfig : ScriptableObject
|
|||||||
return _constantSpawn;
|
return _constantSpawn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public float GetInterval()
|
|
||||||
|
/**
|
||||||
|
* Contains every list of enemy groups
|
||||||
|
*/
|
||||||
|
public List<GroupList> NestedGroupSpawn
|
||||||
{
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _nestedGroupSpawn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public float Interval
|
||||||
|
{
|
||||||
|
get {
|
||||||
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)
|
||||||
@ -37,6 +64,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)
|
||||||
@ -45,5 +76,4 @@ public class WaveConfig : ScriptableObject
|
|||||||
}
|
}
|
||||||
return _enemySum.ToFloat();
|
return _enemySum.ToFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,26 +1,34 @@
|
|||||||
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>();
|
||||||
public WaveConfig LevelConfig
|
private bool _once = true;
|
||||||
|
private int _currentGroupIndex = 0;
|
||||||
|
|
||||||
|
public void SetLevelConfig(WaveConfig config)
|
||||||
{
|
{
|
||||||
set
|
_levelConfig = config;
|
||||||
{
|
|
||||||
_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 +43,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.SetGroupSpawnTimers(_groupSpawnTimers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,7 +58,7 @@ public class WaveObserver : Singleton<WaveObserver>
|
|||||||
public void NotifySpawned(SpawnerTile spawnerSubject)
|
public void NotifySpawned(SpawnerTile spawnerSubject)
|
||||||
{
|
{
|
||||||
GameObject paramPrefab = spawnerSubject.Prefab;
|
GameObject paramPrefab = spawnerSubject.Prefab;
|
||||||
spawnerSubject.ChangeSpawnSpeed(_levelConfig.GetInterval() * _spawnerTiming);
|
spawnerSubject.ChangeSpawnSpeed(_levelConfig.Interval * _spawnerTiming);
|
||||||
if (paramPrefab.Equals(_levelConfig.ConstantSpawn[0].GetEnemyObject()))
|
if (paramPrefab.Equals(_levelConfig.ConstantSpawn[0].GetEnemyObject()))
|
||||||
{
|
{
|
||||||
int currentCount = 0;
|
int currentCount = 0;
|
||||||
@ -136,7 +150,24 @@ public class WaveObserver : Singleton<WaveObserver>
|
|||||||
{
|
{
|
||||||
index = rand.Next(_subjects.Count);
|
index = rand.Next(_subjects.Count);
|
||||||
} while (_intervalTiming.Count <= index);
|
} while (_intervalTiming.Count <= index);
|
||||||
spawnerTile.ChangeSpawnSpeed(_levelConfig.GetInterval() * _intervalTiming[index]);
|
spawnerTile.ChangeSpawnSpeed(_levelConfig.Interval * _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++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -166,7 +166,7 @@ public class LevelManager : Singleton<LevelManager>
|
|||||||
|
|
||||||
_currentLevel = level;
|
_currentLevel = level;
|
||||||
_waveObserver = WaveObserver.Instance;
|
_waveObserver = WaveObserver.Instance;
|
||||||
_waveObserver.LevelConfig = _currentLevel.WaveConfig;
|
_waveObserver.SetLevelConfig(_currentLevel.WaveConfig);
|
||||||
Grid grid = Object.FindObjectOfType<Grid>();
|
Grid grid = Object.FindObjectOfType<Grid>();
|
||||||
//create new grid if there is none
|
//create new grid if there is none
|
||||||
if (!grid)
|
if (!grid)
|
||||||
|
|||||||
@ -16,6 +16,15 @@ 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 void SetGroupSpawnTimers(List<float> groupSpawnTimers)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < groupSpawnTimers.Count-1; i++)
|
||||||
|
{
|
||||||
|
_groupSpawnTimers.Add(groupSpawnTimers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public override void LevelStart()
|
public override void LevelStart()
|
||||||
@ -24,7 +33,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 +45,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 +62,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 +127,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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -15,4 +15,17 @@ MonoBehaviour:
|
|||||||
_constantSpawn:
|
_constantSpawn:
|
||||||
- _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3}
|
- _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3}
|
||||||
_count: 5
|
_count: 5
|
||||||
_gameDuration: 1
|
_nestedGroupSpawn:
|
||||||
|
- groupSpawn:
|
||||||
|
- _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3}
|
||||||
|
_count: 3
|
||||||
|
- _enemy: {fileID: 313037212318601125, guid: 5bbf0d85fa5bb3f4599da79f0a84e3a9, type: 3}
|
||||||
|
_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: 1
|
||||||
|
_gameDuration: 3
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user