Spawning new collectable after one of them is picked (fixed spawning points in 2D)

Hey all, I’m brand new in game dev and I’m working on my first game, in 2D.

I created a simple tilemap level, moveable character, coins that character picks up and a score board that shows total number of coins collected.

Now, I would like the coins to constantly spawn after one of them is picked.

Example:

Fixed spawning point A
Fixed spawning point B
Fixed spawning point C
Fixed spawning point D

  1. At the start of the game, 2 spawning points should create a coin each. Let us say A and C.
  2. After one of the coins is picked up, for example coin A, another coin should spawn on either point B or D (on random).

Is there any way I could accomplish this via editor, with less coding as possible?

Thanks!

I believe you will need some coding anyway since random is involved. But it’s really not that much, something like this

public MySpawnerScript[] ChainedSpawners;

private void HandleItemPickedUp(){
   if(chainedSpawners.Length< 1) return;
   chainedSpawners[Random.Range(0, chainedSpawners.Length)].SpawnItem();
}

After that, you may connect any to any spawners via dragging them into ChainedSpawners inspector field.

1 Like

I think I understand, will give it a shot, thanks! :slight_smile:

Hi and welcome!
You will need some code to keep track of the current number of coins, as well as some knowledge (for example lists) about which locations are occupied or free. You also need to have a number for how many coins should be alive at the same time, in your case 2.
Now you can check if the number of coins is smaller than the desired amount of coins, and if so, pick a random free location, spawn a coin there and mark it as occupied now.
When a coin gets destroyed we do the same in reverse, effectively removing an occupied location and adding a free one. However, since we dont want to respawn a coin on the same location (which happened quite often in my tests), we need to keep track of the just collected coin locations as well, and only make them free again after we spawned the next coin.

The coin manager would look like this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CoinCountManager : MonoBehaviour
{

    private const int DESIRED_COIN_COUNT = 2;
    public int currentCoinCount = 0;
    [SerializeField] private List<Vector3> spawnLocations; // fill this with spawn locations through the editor
    [SerializeField] private CoinScript coinPrefab; // put your coin-prefab in here

    public List<Vector3> freeLocations;
    public List<Vector3> occupiedLocations;
    public List<Vector3> justCollectedLocations;

    // Makes this single instance globally accessable everywhere by calling CoinCountManager.GetInstance()
    private static CoinCountManager singletonInstance;
    public static CoinCountManager GetInstance()
    {
        return singletonInstance;
    }

    private void Start()
    {
        singletonInstance = this;
        freeLocations = spawnLocations;
        occupiedLocations = new List<Vector3>();
        justCollectedLocations = new List<Vector3>();
    }

    public void Update()
    {
        if (currentCoinCount < DESIRED_COIN_COUNT)
        {
            int randIndex = (int)Random.Range(0, freeLocations.Count); // get number between 0 and size of free location list
            Vector3 randSpawn = freeLocations[randIndex];
            freeLocations.Remove(randSpawn); // remove spawn location from free locations
            occupiedLocations.Add(randSpawn); // and add to it to occupied locations
            GameObject newCoin = Instantiate(coinPrefab.gameObject, randSpawn, Quaternion.identity); // instantiate new coin at that location
            currentCoinCount++; // increase current coin count
        }

        // Prevents that we can spawn at locations we just collected from
        if (justCollectedLocations.Count > 0)
        {
            foreach (Vector3 vec in justCollectedLocations)
            {
                occupiedLocations.Remove(vec);
                freeLocations.Add(vec);
            }
            justCollectedLocations.Clear();
        }
    }

    public static void RemoveCoin(CoinScript coin)
    {
        CoinCountManager instance = CoinCountManager.GetInstance();
        instance.justCollectedLocations.Add(coin.transform.position);
        instance.currentCoinCount--;
    }
}

Dont forget to fill in the spawn locations and coinPrefab through the editor.
For your coin prefabs you only need to attach a script with an onDestroy function like this:

public class CoinScript : MonoBehaviour
{
    private void OnDestroy()
    {
        CoinCountManager.RemoveCoin(this);
    }
}

So effectively, first all locations are free. Since we dont want that, the script spawns coins until the desired number of coins is reached, and adds those locations to the occupiedLocations, on which we cannot spawn coins anymore. When a coin gets destroyed (collected) it automatically calls RemoveCoin, which adds its location to the list of just collected coins, to prevent directly freeing its location, which allows a new coin to spawn there.
After the next update loop (new coin was spawned), this list is then cleared and the locations are removed from the list of occupied locations, and added to the list of free locations again.

Using some cubes and an empty game object for testing purposes, the above example does exactly what it should, assuming you manually delete the cubes. Hope the explanations were understandable.

1 Like

@Yoreki WOW … THANKS !!!

Learning game dev is fun, especially with such a great community. Can’t wait to dive into it - thanks once again to both of you! :slight_smile:

1 Like