Search Unity

How can I write a Random.Range Scripts without repetition?

Discussion in 'Scripting' started by cnwcjm9918, May 16, 2019.

  1. cnwcjm9918

    cnwcjm9918

    Joined:
    May 16, 2019
    Posts:
    1
    Hello! Thanks for watching my question.
    I want to make boxes on the chessboard and the boxes are randomly created.
    When player get a box, box disappears and with some seconds later, boxes are recreated.
    So I tried this script, but when I play this script, boxes are successfully randomly created without repetition, but when boxes are fully created, Unity Engine stops and I can't do anything in Unity Engine.
    And when I get a box before boxes are fully created, a box isn't recreated.
    I'm sorry for my bad English. How can I fix this problem?
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class SpawnMgr : MonoBehaviour
    6. {
    7.     public Transform[] points;
    8.     public GameObject boxPrefab;
    9.  
    10.     public float createTime = 2.0f;
    11.     public int maxBox = 10;
    12.  
    13.     public bool isGameOver = false;
    14.  
    15.     List<int> list = new List<int>();
    16.  
    17.     void Start()
    18.     {
    19.         points = GameObject.Find("SpawnPoint").GetComponentsInChildren<Transform>();
    20.  
    21.         if(points.Length > 0)
    22.         {
    23.             StartCoroutine(this.CreateBox());
    24.         }
    25.  
    26.         list = new List<int>(new int[points.Length]);
    27.     }
    28.  
    29.   IEnumerator CreateBox()
    30.     {
    31.         while (!isGameOver)
    32.         {
    33.             int boxCount = (int)GameObject.FindGameObjectsWithTag("Box").Length;
    34.  
    35.             if (boxCount < maxBox)
    36.             {              
    37.                 {
    38.                     for (int j = 0; j <= points.Length; j++)
    39.                     {
    40.                         yield return new WaitForSeconds(createTime);
    41.                         int idx = Random.Range(1, points.Length);
    42.  
    43.                         while (list.Contains(idx))
    44.                         {                          
    45.                             idx = Random.Range(1, points.Length);                          
    46.                         }
    47.  
    48.                         list[j] = idx;
    49.                         Instantiate(boxPrefab, points[idx].position, points[idx].rotation);                      
    50.                         Debug.Log("j =" + j);
    51.                         Debug.Log("idx = " + idx);
    52.                     }
    53.                 }
    54.             }
    55.             else
    56.             {
    57.                 yield return null;
    58.             }
    59.         }
    60.     }
    61. }
    62.  
     
  2. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    You're probably infinitely looping here:

    Code (csharp):
    1. while (list.Contains(idx))
    2. {
    3.     idx = Random.Range(1, points.Length);                        
    4. }
    If you run out of points, there's no way to generate a random point that's not already in the list of points, so Unity's just spinning on that while-loop forever.

    If there's 10 points and maxBox is 10, a simple fix is just to include the first index in your random selection:

    Code (csharp):
    1. Random.Range(1, points.Length);
    But if you're destroying boxes, that won't be enough; you have to return the used spots to the list of spots.
     
  3. zakpacha

    zakpacha

    Joined:
    Nov 28, 2016
    Posts:
    12
    You're starting a co-routine which uses your "list" variable, then right after you do this:
    list = new List<int>(new int[points.Length]);

    i dont think you want to do that, or at least wait for your coroutine to finish as they would run side-by-side.