如何防止同一预制件在 Unity 中连续生成两次

How to prevent same prefab from spawning twice in a row in Unity

这里是 Unity 初学者,我在 Unity 中的游戏中附加了一个随机预制件生成器,它随机生成 3 个预制件。问题是,有时我会连续 5 次获得相同的预制件。如何防止同一个预制件连续生成两次?这是我的代码:

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;
        }   
    }
}

好吧,只需声明将新的随机预制件与之前的随机预制件进行检查即可。 对于懒代码,你可以

GameObject previousPrefab;

然后在随机化中,将 previousPrefab 设置为随机化的预制件。

然后在下一次随机化中,检查previousPrefab == randomizedPrefab,如果是, 再次随机化。

^ 同样,要实现这样的目标,您必须从 Update() 部分创建一个方法并在 Update() 中调用它,这样如果先前的预制件与随机预制件相同,您就可以再次调用该方法。

使用 Unity 内置随机系统的一种简单方法是创建一个可能生成的数字列表,然后从该列表中选择一个随机数,如下所示:

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)];
    }
}

或者,更简单的方法是一直生成一个数字,直到你得到一个你满意的数字,就像这样:

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

        return generatedNumber;
    }
如果您决定使用 System.Random 提供的 .NET,

This 可以提供帮助。

另外请注意,目前您的大部分 values/variables 都是硬编码。
(也就是说,它不适合生成超过 4 种类型的预制件)

Unity Inspector 也接受数组,因此您可以利用它并像这样重构您的代码:

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)];
    }
}