Symbi-Node

SymbiNode, a survivor-like game developed within a 72-hour game jam using Unity. In this project, I implemented an enemy spawn and stage progression system using scriptable objects to efficiently store crucial data. This approach provided flexibility for quick adjustments during the time-constrained game jam.

Code Snippets

Object Pooler

public class ObjectPooler : MonoBehaviour
{
    public List<Pool> PoolList = new List<Pool>();
    public ObjectPooler Instance { get; private set; }

    private void Awake()
    {
        if (Instance != null)
        {
            Destroy(this.gameObject);
        }
        else
        {
            Instance = this;
        }
    }

    private void Start()
    {
        foreach (var pool in PoolList)
        {
            for (int i = 0; i < pool.PoolStartSize; i++)
            {
                GameObject newObject = Instantiate(pool.Prefab) as GameObject;
                pool.ObjectPool.Enqueue(newObject);
                newObject.SetActive(false);
            }
        }
    }

    public GameObject GetObject(string poolTag)
    {
        var desiredPool = PoolList.Find(p => p.Tag == poolTag);

        if (desiredPool.ObjectPool.Count > 0)
        {
            GameObject newObject = desiredPool.ObjectPool.Dequeue();
            newObject.SetActive(true);
            return newObject;
        }
        else
        {
            GameObject newObject = Instantiate(desiredPool.Prefab) as GameObject;
            return newObject;
        }
    }

    public GameObject GetObject(GameObject targetPrefab)
    {
        var desiredPool = PoolList.Find(p => p.Tag == targetPrefab.GetComponent<Enemy>().valuesSO.tag);
        Debug.Log("Desired pool is " + desiredPool.Tag);

        if (desiredPool.ObjectPool.Count > 0)
        {
            GameObject newObject = desiredPool.ObjectPool.Dequeue();
            newObject.SetActive(true);
            return newObject;
        }
        else
        {
            GameObject newObject = Instantiate(desiredPool.Prefab) as GameObject;
            return newObject;
        }
    }

    public void ReturnObject(string poolTag, GameObject objectToReturn)
    {
        var desiredPool = PoolList.Find(p => p.Tag == poolTag);

        desiredPool.ObjectPool.Enqueue(objectToReturn);
        objectToReturn.SetActive(false);
    }

    [Serializable]
    public class Pool
    {
        public string Tag;
        public GameObject Prefab;
        public int PoolStartSize = 5;
        public Queue<GameObject> ObjectPool = new Queue<GameObject>();
    }
}

Spawner

public class SpawnerAdvanced : MonoBehaviour
{
    [SerializeField] private List<StageSO> allStages = new List<StageSO>();
    [SerializeField] private GameObject bossPrefab;
    [SerializeField] private float bossSpawnTime;
    public List<Transform> spawnPlaces;
    private bool _bossSpawned = false;
    private StageSO _currentStage;

    private ObjectPooler _objectPool;
    private int _stageIndex = 0;
    public Queue<GameObject> EnemyQueue = new Queue<GameObject>();


    private void Start()
    {
        _objectPool = FindObjectOfType<ObjectPooler>();
        _currentStage = allStages[_stageIndex];
        SetEnemyQueue();

        Invoke(nameof(SpawnBoss), bossSpawnTime);
    }

    private void FixedUpdate()
    {
        SpawnNonBossEnemies();
    }

    private void SetEnemyQueue()
    {
        foreach (var enemy in _currentStage.enemies)
        {
            EnemyQueue.Enqueue(enemy);
        }
    }

    private void SpawnNonBossEnemies()
    {
        if (!_bossSpawned)
        {
            _currentStage.timeSinceSpawn += Time.deltaTime;

            if (_currentStage.timeSinceSpawn >= _currentStage.timeTakesToSpawn)
            {
                if (EnemyQueue.Count <= 0)
                {
                    if (_stageIndex + 1 != allStages.Count)
                    {
                        _stageIndex++;
                        _currentStage = allStages[_stageIndex];
                        SetEnemyQueue();
                    }
                    else
                    {
                        Debug.Log("Stage finished, stage was " + _currentStage);
                        //this.gameObject.SetActive(false);
                    }
                }
                else
                {
                    Debug.Log(EnemyQueue.Peek());
                    GameObject newObject = _objectPool.GetObject(EnemyQueue.Dequeue());
                    newObject.transform.position = spawnPlaces[Random.Range(0, spawnPlaces.Count)].position;
                    newObject.SetActive(true);
                    _currentStage.timeSinceSpawn = 0f;
                }
            }
        }
    }

    private void SpawnBoss()
    {
        Instantiate(bossPrefab, spawnPlaces[Random.Range(0, spawnPlaces.Count)]);
        _bossSpawned = true;
    }
}