IEnumerator Freezes The Whole Game

IEnumerator ContentSpawnProcedure(List<string> listToSpawn, DataForBoxSpawning dataForBoxSpawning)
{
    Debug.Log("Coroutine ContentSpawnProcedure started");

    Box b = currentBox.transform.Find("Box").GetComponent<Box>();
    Debug.Log("Box component fetched");

    b.contents = listToSpawn; // Save the items list to the box
    Debug.Log("List assigned to box contents");

    Dictionary<string, GameObject> prefabsDictionary = dataForBoxSpawning.RequestDictionary(b.boxContentType); // Get the prefab data to spawn
    Debug.Log("Prefabs dictionary fetched");

    List<GameObject> spawnedObjectsList = new List<GameObject>(); // Track spawned objects for later processing
    Debug.Log("Spawned objects list initialized");

    for (int i = 0; i < listToSpawn.Count; i++)
    {
        Debug.Log($"Spawning object for list item {i}: {listToSpawn[i]}");

        GameObject spawningObj;

        if (prefabsDictionary.ContainsKey(listToSpawn[i]))
        {
            spawningObj = prefabsDictionary[listToSpawn[i]];
            Debug.Log($"Found prefab for {listToSpawn[i]}");
        }
        else
        {
            spawningObj = null;
            Debug.LogError($"Key {listToSpawn[i]} wasn't found in the dictionary");
        }

        GameObject spawnedObj = Instantiate(spawningObj, dataForBoxSpawning.TEST_ContentSpawnPos.position, dataForBoxSpawning.TEST_ContentSpawnPos.rotation, null);
        Debug.Log($"Instantiated object: {spawnedObj.name}");

        spawnedObjectsList.Add(spawnedObj);
        Debug.Log("Added object to spawnedObjectsList");

        yield return new WaitForSeconds(0.3f); // Delay between spawns
        Debug.Log("Waited 0.3 seconds before next spawn");
    }

    Debug.Log("Starting post-spawn processing");

    foreach (GameObject item in spawnedObjectsList)
    {
        Debug.Log($"Processing item: {item.name}");

        Rigidbody rb = item.GetComponent<Rigidbody>();
        Debug.Log("Rigidbody component fetched");

        float startTime = Time.time;
        Debug.Log("Start time recorded");

        // Wait for the object to stop moving or until timeout
        while (rb.velocity.magnitude >= 0.1f)
        {
            Debug.Log($"Object {item.name} velocity: {rb.velocity.magnitude}");

            if (Time.time - startTime > 7f) // Timeout after 7 seconds
            {
                Debug.LogWarning($"Timeout: Object {item.name} did not stop moving, forcing kinematic state.");
                break;
            }
            yield return null;
        }

        rb.isKinematic = true;
        rb.useGravity = false; // Completely freeze the item
        Debug.Log($"Object {item.name} frozen and kinematic set");

        item.transform.SetParent(currentBox.transform.Find("Contents"));
        Debug.Log($"Object {item.name} parent set to Contents");
    }

    Debug.Log("Clearing spawnedObjectsList");
    spawnedObjectsList.Clear(); // Clear the list after completing the spawning procedure

    Debug.Log("Deleting overcolliding items");
    DeleteBoxOvercollider(dataForBoxSpawning); // Delete items colliding with the box lid

    Debug.Log("Stopping ContentSpawnProcedure coroutine");
    StopCoroutine(ContentSpawnProcedure(null, dataForBoxSpawning));
}

In every 1 out of 10 runs (aprox.) my game freezez, i posted another coroutine which i thought made the game freeze but no its this one.

Well, better start debugging, maybe even disabling swaths of the code to isolate things. At a quick glance your loops look like they all have yields but perhaps some other method in there has an infinite loop, such as a loop that iterates a collection while adding to it.

Unity will lock up 100% of the time EVERY millisecond your scripting code is running.

Nothing will render, no input will be processed, no Debug.Log() will come out, no GameObjects or transforms will appear to update.

Absolutely NOTHING will happen… until your code either:

  • returns from whatever function it is running

  • yields from whatever coroutine it is running

As long as your code is looping, Unity isn’t going to do even a single frame of change. Nothing.

No exceptions.

“Yield early, yield often, yield like your game depends on it… it does!” - Kurt Dekker

When the game crashes in the editor, you want to go check the logs. See the last few messages and scan for any exceptions.

They can be LARGE sometimes, so getting a proper log viewer (I use klogg) can be required. They probably won’t be in this case.


On a quick pass of your script, I’m not seeing an obvious infinite loop. But you have a lot of Debug.Logs already so pinpointing where it’s looping should be easy.


One fact that makes me hesitate to suspect this script is your statement here:

In every 1 out of 10 runs (aprox.) my game freezez

I’m not seeing a “1 out of 10” kind of thing, like usage of Random.

Ä° got it to freeze in the first trial than checked the editor log. It looked like litteraly no operation was called. (yes it shows what has been done if it doesent freeze). There are Unity.Random i am using i will give you the whole code now. Sorry for if its a mees i am not much experienced in long scripts

The part that uses UnityEngine.Random is BoxSenderTypeRandomizer and BoxContentTypeRandomizer

using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UIElements;

public class BoxSpawningHandler : MonoBehaviour
{
    #region RandomBoxCreationLists
    string[] boxSenderTypes = { "normal", "mafia", "smuggler" };
    string[] normalSenderBoxTypes = { "daily", "fragile", "valuable", "explosive" };
    string[] mafiaSenderBoxTypes = { "valuable", "explosive", "weapon", "banned", "smuggled", "misc" };
    string[] smugglerSenderBoxTypes = { "valuable", "banned", "smuggled", "misc" };
    #endregion
    #region SpawnBoxHandlingVariables
    GameObject currentBox;
    GameObject lastBox;
    #endregion
    private GameHandler gameHandler;

    public void StopLastBox() // Debug For Stopping And Deleting Current Coroutine
    {
        Destroy(lastBox);
    }
    public void StartBoxSpawning(DataForBoxSpawning dataForBoxSpawning) // To Start CoRoutine From Another Script
    {
        BoxSpawning(dataForBoxSpawning);
    }

    private void Awake()
    {
        gameHandler = GetComponent<GameHandler>();
    }
    void BoxSpawning(DataForBoxSpawning dataForBoxSpawning)
    {
        GameObject box = Instantiate(dataForBoxSpawning.TEST_BoxPrefab, dataForBoxSpawning.TEST_BoxSpawnPos.position, dataForBoxSpawning.TEST_BoxSpawnPos.rotation, null);
        currentBox = box;
        if (box == null)
        {
            Debug.LogError("Box prefab oluşturulamadı! Box null döndü.");
        }

        Rigidbody rb = box.GetComponent<Rigidbody>();

        Box b = box.transform.Find("Box")?.GetComponent<Box>();
        if (b == null)
        {
            Debug.LogError("Box bileşeni bulunamadı!");
        }

        rb.useGravity = false;
        rb.isKinematic = true; // Box donduruldu

        var senderType = BoxSenderTypeRandomiser(gameHandler.Day);
        b.boxSenderType = senderType;
        if (senderType == null)
        {
            Debug.LogError("BoxSenderTypeRandomiser null döndürdü!");
        }

        var contentType = BoxContentTypeRandomiser(gameHandler.Day, senderType);
        b.boxContentType = contentType;
        if (contentType == null)
        {
            Debug.LogError("BoxContentTypeRandomiser null döndürdü!");
        }

        SpawningContentListRandomizer(contentType, dataForBoxSpawning);
    }
    string BoxSenderTypeRandomiser(int day)
    {
        int x = UnityEngine.Random.Range(0, 101);
        if (gameHandler.GameState == GameState.Infinite)
        {
            return null; // Fill This Place When You Start Adding Infinite
        }
        else if (gameHandler.GameState == GameState.Campaign)
        {
            if (day <= 10)
            {
                return x <= 75 ? "Normal" : x <= 90 ? "Government" : "Mafia";
            }
            else if (day <= 30)
            {
                return x <= 60 ? "Normal" : x <= 82 ? "Government" : "Mafia";
            }
            else if (day > 30)
            {
                return x <= 45 ? "Normal" : x <= 73 ? "Government" : "Mafia";
            }

            else { Debug.LogError($"Ä°nvalid Day For Campaign: {day}"); return null; }
        }
        else
        {
            Debug.LogError($"Ä°nvalid Call Time | Game State {gameHandler.GameState.ToString()}"); return null;
        }
    }
    string BoxContentTypeRandomiser(int day, string senderType)
    {
        int x = UnityEngine.Random.Range(0, 101);
        var senderActions = new Dictionary<string, Func<int, int, string>>
        {
           { "Normal", (day, x) => HandleNormal(day, x) },
           { "Government", (day, x) => HandleGovernment(day, x) },
           { "Mafia", (day, x) => HandleMafia(day, x) },
        };
        if (gameHandler.GameState == GameState.Infinite)
        {
            return null;
        }
        else if (gameHandler.GameState == GameState.Campaign)
        {
            if (senderActions.ContainsKey(senderType))
            {
                return senderActions[senderType].Invoke(day, x);
            }
            else { Debug.LogError($"Invalid Sender Type: {senderType}"); return null; }
        }
        else { Debug.LogError("Invalid Expection In Wrong Screen " + gameHandler.GameState.ToString()); return null; }

        string HandleNormal(int day, int r)
        {
            if (day <= 10)
            {
                return r <= 65 ? "Daily" : r <= 77 ? "Fragile" : r <= 87 ? "Valuable" : "Electronics";
            }
            else if (day <= 30)
            {
                return r <= 45 ? "Daily" : r <= 60 ? "Fragile" : r <= 75 ? "Valuable" : "Electronics";
            }
            else if (day > 30)
            {
                return r <= 25 ? "Daily" : r <= 50 ? "Fragile" : r <= 75 ? "Valuable" : "Electronics";
            }
            else { Debug.LogError("Ä°nvalid Day Type"); return null; }
        }

        string HandleGovernment(int day, int r)
        {
            if (day <= 10)
            {
                return r <= 60 ? "Equipment" : r <= 80 ? "Money" : r <= 90 ? "Weapon" : "Explosive";
            }
            else if (day <= 30)
            {
                return r <= 50 ? "Equipment" : r <= 75 ? "Money" : r <= 90 ? "Weapon" : "Explosive";
            }
            else if (day > 30)
            {
                return r <= 45 ? "Equipment" : r <= 65 ? "Money" : r <= 80 ? "Weapon" : "Explosive";
            }
            else { Debug.LogError("Ä°nvalid Day Type"); return null; }
        }

        string HandleMafia(int day, int r)
        {
            if (day <= 10)
            {
                return r <= 60 ? "Cigarette" : r <= 80 ? "Cigar" : r <= 95 ? "MafiaWeapon" : "Drug";
            }
            else if (day <= 30)
            {
                return r <= 50 ? "Cigarette" : r <= 80 ? "Cigar" : r <= 90 ? "MafiaWeapon" : "Drug";
            }
            else if (day > 30)
            {
                return r <= 40 ? "Cigarette" : r <= 55 ? "Cigar" : r <= 78 ? "MafiaWeapon" : "Drug";
            }
            else { Debug.LogError("Ä°nvalid Day Type"); return null; }
        }
    }
    void SpawningContentListRandomizer(string contentType, DataForBoxSpawning dataForBoxSpawning)
    {
        int ContentSpawnCountHandler(int howManyTypes)
        {
            if (howManyTypes == 1)
            {
                return UnityEngine.Random.Range(5, 10);
            }
            else if (howManyTypes < 4)
            {
                return UnityEngine.Random.Range(3, 6);
            }
            else
            {
                return UnityEngine.Random.Range(2, 5);
            }
        }
        int IfOneTime = PercentageRandom(20);
        List<string> result = new List<string>();

        //For Speacial Cases
        if (contentType == "Valuable" || contentType == "Equipment" || contentType == "Weapon" || contentType == "MafiaWeapon")
        {
            IfOneTime = 1;
        }
        if (contentType == "Explosive" || contentType == "Money" || contentType == "Cigar" || contentType == "Cigarette")
        {
            IfOneTime = 0;
        }
        List<string> itemsList = dataForBoxSpawning.RequestList(contentType, IfOneTime);

        int count = itemsList.Count;
        if (IfOneTime == 1)
        {
            int random = UnityEngine.Random.Range(0, count);
            result.Add(itemsList[random]);
            StartCoroutine(ContentSpawnProcedure(result, dataForBoxSpawning));
        }
        else if (IfOneTime == 0)
        {
            int numberOfDifferentItems = UnityEngine.Random.Range(1, 5);
            HashSet<int> set = new HashSet<int>();
            for (int i = 0; i < numberOfDifferentItems; i++)
            {
                int random = UnityEngine.Random.Range(0, count);
                while (set.Contains(random))
                {
                    random = UnityEngine.Random.Range(0, count);
                }
                set.Add(random);
                for (int j = 0; j < ContentSpawnCountHandler(numberOfDifferentItems); j++)
                {
                    result.Add(itemsList[random]);
                }
            }
            StartCoroutine(ContentSpawnProcedure(result, dataForBoxSpawning));
        }
        else { Debug.LogError($"Invalid Percantage Value {IfOneTime}"); }
    }
    IEnumerator ContentSpawnProcedure(List<string> listToSpawn, DataForBoxSpawning dataForBoxSpawning)
    {
        Debug.Log("Coroutine ContentSpawnProcedure started");

        Box b = currentBox.transform.Find("Box").GetComponent<Box>();
        Debug.Log("Box component fetched");

        b.contents = listToSpawn; // Save the items list to the box
        Debug.Log("List assigned to box contents");

        Dictionary<string, GameObject> prefabsDictionary = dataForBoxSpawning.RequestDictionary(b.boxContentType); // Get the prefab data to spawn
        Debug.Log("Prefabs dictionary fetched");

        List<GameObject> spawnedObjectsList = new List<GameObject>(); // Track spawned objects for later processing
        Debug.Log("Spawned objects list initialized");

        for (int i = 0; i < listToSpawn.Count; i++)
        {
            Debug.Log($"Spawning object for list item {i}: {listToSpawn[i]}");

            GameObject spawningObj;

            if (prefabsDictionary.ContainsKey(listToSpawn[i]))
            {
                spawningObj = prefabsDictionary[listToSpawn[i]];
                Debug.Log($"Found prefab for {listToSpawn[i]}");
            }
            else
            {
                spawningObj = null;
                Debug.LogError($"Key {listToSpawn[i]} wasn't found in the dictionary");
            }

            GameObject spawnedObj = Instantiate(spawningObj, dataForBoxSpawning.TEST_ContentSpawnPos.position, dataForBoxSpawning.TEST_ContentSpawnPos.rotation, null);
            Debug.Log($"Instantiated object: {spawnedObj.name}");

            spawnedObjectsList.Add(spawnedObj);
            Debug.Log("Added object to spawnedObjectsList");

            yield return new WaitForSeconds(0.3f); // Delay between spawns
            Debug.Log("Waited 0.3 seconds before next spawn");
        }

        Debug.Log("Starting post-spawn processing");

        foreach (GameObject item in spawnedObjectsList)
        {
            Debug.Log($"Processing item: {item.name}");

            Rigidbody rb = item.GetComponent<Rigidbody>();
            Debug.Log("Rigidbody component fetched");

            float startTime = Time.time;
            Debug.Log("Start time recorded");

            // Wait for the object to stop moving or until timeout
            while (rb.velocity.magnitude >= 0.1f)
            {
                Debug.Log($"Object {item.name} velocity: {rb.velocity.magnitude}");

                if (Time.time - startTime > 7f) // Timeout after 7 seconds
                {
                    Debug.LogWarning($"Timeout: Object {item.name} did not stop moving, forcing kinematic state.");
                    break;
                }
                yield return null;
            }

            rb.isKinematic = true;
            rb.useGravity = false; // Completely freeze the item
            Debug.Log($"Object {item.name} frozen and kinematic set");

            item.transform.SetParent(currentBox.transform.Find("Contents"));
            Debug.Log($"Object {item.name} parent set to Contents");
        }

        Debug.Log("Clearing spawnedObjectsList");
        spawnedObjectsList.Clear(); // Clear the list after completing the spawning procedure

        Debug.Log("Deleting overcolliding items");
        DeleteBoxOvercollider(dataForBoxSpawning); // Delete items colliding with the box lid

        yield break;
    }
    void DeleteBoxOvercollider(DataForBoxSpawning dataForBoxSpawning)
    {
        List<GameObject> list = currentBox.transform.Find("Collider").GetComponent<ColliderScript>().ItemsToDelete;
        Box _box = currentBox.transform.Find("Box").GetComponent<Box>();
        foreach (var item in list)
        {
            string _name = item.name.Replace("(Clone)", "");
            if (_box.contents.Contains(_name))
            {
                _box.contents.Remove(_name);
            }
            else { Debug.LogError($"Item {_name} couldnt be found in contents list of currentBox"); }
            Destroy(item);
        }
        currentBox.transform.Find("Lid").gameObject.SetActive(true);
        BoxValueSetter(dataForBoxSpawning);
    }
    void BoxValueSetter(DataForBoxSpawning dataForBoxSpawning)
    {
        Box b = currentBox.transform.Find("Box").GetComponent<Box>();
        foreach (string itemName in b.contents)
        {
            b.boxValue += dataForBoxSpawning.itemPrices[itemName];
        }
        BoxPropertySetter(dataForBoxSpawning);
    }
    void BoxPropertySetter(DataForBoxSpawning dataForBoxSpawning)
    {
        Box b = currentBox.transform.Find("Box").GetComponent<Box>();
        int boxValue = b.boxValue;
        if (gameHandler.Day <= 10)
        {
            b.boxMaintenance = boxValue * 15 / 100;
            b.boxOpeningFee = boxValue * 40 / 100;
            b.boxSuccesMoney = boxValue * 115 / 100;
            b.boxFailFee = boxValue * 80 / 100;
            b.boxAcceptanceFee = boxValue * 30 / 100;
        }
        else if (gameHandler.Day <= 30)
        {
            b.boxMaintenance = boxValue * 30 / 100;
            b.boxOpeningFee = boxValue * 40 / 100;
            b.boxSuccesMoney = boxValue * 117 / 100;
            b.boxFailFee = boxValue * 90 / 100;
            b.boxAcceptanceFee = boxValue * 35 / 100;
        }
        else if (gameHandler.Day <= 50)
        {
            b.boxMaintenance = boxValue * 45 / 100;
            b.boxOpeningFee = boxValue * 40 / 100;
            b.boxSuccesMoney = boxValue * 120 / 100;
            b.boxFailFee = boxValue * 90 / 100;
            b.boxAcceptanceFee = boxValue * 40 / 100;
        }
        BoxSenderNameSetter(dataForBoxSpawning);
    }
    void BoxSenderNameSetter(DataForBoxSpawning dataForBoxSpawning)
    {
        string FirstName;
        string LastName;
        Box b = currentBox.transform.Find("Box").GetComponent<Box>();
        if (b.boxSenderType == "Mafia" && PercentageRandom(50) == 1)
        {
            FirstName = dataForBoxSpawning.companyFirstNameFake[UnityEngine.Random.Range(0, dataForBoxSpawning.companyFirstNameFake.Length)];
            LastName = dataForBoxSpawning.companyType[UnityEngine.Random.Range(0, dataForBoxSpawning.companyType.Length)];
        }
        else
        {
            FirstName = dataForBoxSpawning.companyFirstName[UnityEngine.Random.Range(0, dataForBoxSpawning.companyFirstName.Length)];
            LastName = dataForBoxSpawning.companyType[UnityEngine.Random.Range(0, dataForBoxSpawning.companyType.Length)];
        }
        b.senderCompany = FirstName + " " + LastName;
        BoxReqsSetter();
    }
    void BoxReqsSetter()
    {
        Box b = currentBox.transform.Find("Box").GetComponent<Box>();
        string Type = b.boxContentType;
        if (gameHandler.Day <= 10)
        {
            int x = PercentageRandom(15);
            if (x == 1)
            {
                switch (Type)
                {
                    case "Fragile":
                        b.boxReqs.Add("Pouch");
                        break;
                    case "Electronics":
                        b.boxReqs.Add("MiniFridge");
                        break;
                    case "Explosive":
                        b.boxReqs.Add("AntiExplosiveBox");
                        break;
                }
            }
        }

        else if (gameHandler.Day <= 30)
        {
            int x = PercentageRandom(25);
            if (x == 1)
            {
                switch (Type)
                {
                    case "Fragile":
                        b.boxReqs.Add("Pouch");
                        break;
                    case "Electronics":
                        b.boxReqs.Add("MiniFridge");
                        break;
                    case "Explosive":
                        b.boxReqs.Add("AntiExplosiveBox");
                        break;
                    default:
                        Debug.LogError($"Box Content Type {b.boxContentType} Ä°snt Valid");
                        break;
                }
            }

        }
        else if (gameHandler.Day <= 50)
        {
            int x = PercentageRandom(35);
            if (x == 1)
            {
                switch (Type)
                {
                    case "Fragile":
                        b.boxReqs.Add("Pouch");
                        break;
                    case "Electronics":
                        b.boxReqs.Add("MiniFridge");
                        break;
                    case "Explosive":
                        b.boxReqs.Add("AntiExplosiveBox");
                        break;
                    default:
                        Debug.LogError($"Box Content Type {b.boxContentType} Ä°snt Valid");
                        break;
                }
            }
        }
        else { Debug.LogError($"Ä°nvalid Day Given {gameHandler.Day}"); }
        PrintBox();
        EndRoutine();
    }
    void EndRoutine()
    {
        lastBox = currentBox;
        currentBox = null;
    }
    void PrintBox() //Debugging Function
    {
        /*Box b = currentBox.transform.Find("Box").GetComponent<Box>();

        Debug.Log("Days to Stay: " + b.daysToStay);
        Debug.Log("Box Breakability: " + b.boxBreakability);

        Debug.Log("Box Requirements: ");
        foreach (var req in b.boxReqs)
        {
            Debug.Log(" - " + req);
        }

        Debug.Log("Contents: ");
        foreach (var content in b.contents)
        {
            Debug.Log(" - " + content);
        }

        Debug.Log("Box Content Type: " + b.boxContentType);
        Debug.Log("Box Sender Type: " + b.boxSenderType);
        Debug.Log("Sender Company: " + b.senderCompany);

        Debug.Log("Box Value: " + b.boxValue);
        Debug.Log("Box Maintenance: " + b.boxMaintenance);
        Debug.Log("Box Acceptance Fee: " + b.boxAcceptanceFee);
        Debug.Log("Box Opening Fee: " + b.boxOpeningFee);
        Debug.Log("Box Success Money: " + b.boxSuccesMoney);
        Debug.Log("Box Fail Fee: " + b.boxFailFee);
        */ //Debugging
    }





    /// <summary>
    /// This Function Returns 1 Given Percantage Wins, 0 Ä°f Doesent
    /// </summary>
    int PercentageRandom(int Percant)
    {
        int x = UnityEngine.Random.Range(0, 101);
        if (x <= Percant)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
}

Correct. As noted in my post above:

No logging appears until your code returns or yields to Unity.

NOTE: This is crazy mad scientist code and should be avoided at all costs:

Use an adaptor pattern where you have a known Component you interface with to do everything.

Keep in mind that using GetComponent() and its kin (in Children, in Parent, plural, etc) to try and tease out Components at runtime is definitely deep into super-duper-uber-crazy-Ninja advanced stuff.

Here’s the bare minimum of stuff you absolutely MUST keep track of if you insist on using these crazy Ninja methods:

  • what you’re looking for:
    → one particular thing?
    → many things?
  • where it might be located (what GameObject?)
  • where the Get/Find command will look:
    → on one GameObject? Which one? Do you have a reference to it?
    → on every GameObject?
    → on a subset of GameObjects?
  • what criteria must be met for something to be found (enabled, named, etc.)
  • if your code expects one instance and later you have many (intentional or accidental), does it handle it?

If you are missing knowledge about even ONE of the things above, your call is likely to FAIL.

This sort of coding is to be avoided at all costs unless you know exactly what you are doing.

Botched attempts at using Get- and Find- are responsible for more crashes than useful code, IMNSHO.

If you run into an issue with any of these calls, start with the documentation to understand why.

There is a clear set of extremely-well-defined conditions required for each of these calls to work, as well as definitions of what will and will not be returned.

In the case of collections of Components, the order will NEVER be guaranteed, even if you happen to notice it is always in a particular order on your machine.

It is ALWAYS better to go The Unity Way™ and make dedicated public fields and drag in the references you want.

1 Like

Unity freezes are almost always a result of an incorrectly setup while loop that leads to an infinite loop. From a quick look at your code I see this possibly problematic while loop:

int random = UnityEngine.Random.Range(0, count);
while (set.Contains(random))
{
     random = UnityEngine.Random.Range(0, count);
}
set.Add(random);

I can see a possibility where, if set contains every number from 0 to count, then the while loop will just keep looping forever, causing Unity to freeze.

1 Like

Yes, this is most likely the issue and generally a bad to horrible approach as well. If you want to randomize an array with a set number of elements, you better use a classical Fisher-Yates-Shuffle. Here’s an example method that shuffles an array. Note that you may want to create a duplicate array or List that you shuffle. Once shuffled you can simply iterate through the array in order and you get them in a random order.

Just to make this clear, currently whenever your count is smaller than numberOfDifferentItems the code will 100% freeze. If you only have 4 distinct items and you try to iterate 5 times, of course you won’t find any item for the last iteration that hasn’t yet been used.

2 Likes