0

Unity beginner here, I have a random prefab spawner attached to my game in Unity which randomly spawns 3 prefabs. The problem is, sometimes I get the same prefab like 5 times in a row. How can I prevent the same prefab from spawning twice in a row? Here is my code:

public class randomspawnscript : MonoBehaviour
{
    public GameObject prefab1, prefab2, prefab3;


    public float spawnRate = 2f;

    float nextSpawn = 0f;

    int whatToSpawn;

    void Update()
    {
        if (collisionbutton.end != true || gameoverscreenrestart.restartPressed==true || gameovermainmenu.menuPressed==true)
        {
            if (Time.time > nextSpawn)
            {
                whatToSpawn = Random.Range(1, 4);
                Debug.Log(whatToSpawn);

                switch (whatToSpawn)
                {
                    case 1:
                        Instantiate(prefab1, transform.position, Quaternion.identity);
                        break;
                    case 2:
                        Instantiate(prefab2, transform.position, Quaternion.identity);
                        break;
                    case 3:
                        Instantiate(prefab3, transform.position, Quaternion.identity);
                        break;
                }
                nextSpawn = Time.time + spawnRate;
            }
        }
        else
        {
            return;
        }   
    }
}
vaso
  • 39
  • 1
  • 7
  • how about save the last spawned item and if you random it, random again until you get new one? that 1 way I guess. – Talg123 Sep 28 '19 at 19:07

2 Answers2

0

Well, just make a statement that checks the new randomized Prefab with the previous randomized prefab. For the lazy code, you can just

GameObject previousPrefab;

and in Randomization, set the previousPrefab to the randomized prefab.

and in next Randomization, check if the previousPrefab == randomizedPrefab, if yes, randomize again.

^ Also to achieve something like this you have to create a method from your Update() section and call it in Update() so you can call the method again if the previousPrefab is the same as the randomized one.

0

A simple way using the Unity's in build Random system is just to create a list of possible generated numbers, and pick a random number from that list, like so:

public class randomspawnscript : MonoBehaviour {
    public GameObject prefab1, prefab2, prefab3;

    public float spawnRate = 2f;

    float nextSpawn = 0f;

    int whatToSpawn;

    private void Awake() {
        // To not get a null ref error when generating the controlled random
        // for the first time.
        whatToSpawn = 0;
    }

    void Update() {
        if (/* ... */) {
            if (Time.time > nextSpawn) {
                whatToSpawn = GetControlledRandom();
                Debug.Log(whatToSpawn);

                switch (whatToSpawn) {
                    //...
                }
                nextSpawn = Time.time + spawnRate;
            }
        } else {
            return;
        }
    }

    int GetControlledRandom() {
        List<int> possibleChoices = new List<int> {
            1, 2, 3
        };

        // Removes what was spawned before from the possible choices.
        possibleChoices.Remove(whatToSpawn);

        return possibleChoices[Random.Range(0, possibleChoices.Count)];
    }
}

Alternatively, the more simpler way is to just keep generating a number until you get the one you are satisfied with, like so:

    int RetardedControlledRandom() {
        int generatedNumber;
        do {
            generatedNumber = Random.Range(1, 4);
        } while (generatedNumber == whatToSpawn);

        return generatedNumber;
    }

This can help if you decide to use the .NET provided System.Random instead.

Also, note that currently most of your values/variables are hardcode.
(Aka it does not dynamically suit to spawning more than 4 types of prefab)

Unity Inspector accepts an array too, so you can make use of that and refactor your code like so:

public class randomspawnscript : MonoBehaviour {
    public GameObject[] possibleSpawnPrefabs;

    public float spawnRate = 2f;

    float nextSpawn = 0f;

    int whatToSpawn;

    private void Awake() {
        whatToSpawn = 0;
    }

    void Update() {
        if (collisionbutton.end != true || gameoverscreenrestart.restartPressed == true || gameovermainmenu.menuPressed == true) {
            if (Time.time > nextSpawn) {
                whatToSpawn = GetControlledRandom();
                Debug.Log(whatToSpawn);

                var prefabToSpawn = possibleSpawnPrefabs[whatToSpawn];
                Instantiate(prefabToSpawn, transform.position, Quaternion.identity);

                nextSpawn = Time.time + spawnRate;
            }
        } else {
            return;
        }
    }

    int GetControlledRandom() {
        List<int> possibleChoices = new List<int>();

        for (int i = 0; i < possibleSpawnPrefabs.Length; ++i) {
            possibleChoices.Add(i);
        }

        // Removes what was spawned before from the possible choices.
        possibleChoices.Remove(whatToSpawn);

        return possibleChoices[Random.Range(0, possibleChoices.Count)];
    }
} 
WQYeo
  • 3,973
  • 2
  • 17
  • 26
  • Thank you so much for such quick and detailed response, not only did this solve my problem but it also optimized my project. Many thanks! – vaso Sep 28 '19 at 22:12