Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Swapping the GameObject's children in a random way.

Discussion in 'Scripting' started by begimotique, Mar 25, 2019.

Thread Status:
Not open for further replies.
  1. begimotique

    begimotique

    Joined:
    Feb 10, 2019
    Posts:
    2
    Hello, guys. I need your help.

    I have a game object, that spawns 9 it's children. Like:

    1 2 3
    4 5 6
    7 8 9

    Is there a way to swap them all in random order without getting duplicates. It have to be like this:

    5 4 3
    1 8 9
    2 6 7

    Thanks.
     
  2. KDevS

    KDevS

    Joined:
    Dec 4, 2018
    Posts:
    7
    When you say "it has to be like this", I am assuming that you mean the visual placement of the child objects. Put the children objects in an array/list before spawning them, shuffle the array/list and then spawn them the usual way?
     
  3. Magiichan

    Magiichan

    Joined:
    Jan 5, 2014
    Posts:
    403
    Code (CSharp):
    1.  
    2.     public static void Randomize<T>(T[] items)
    3.     {
    4.         Random rand = new Random();
    5.  
    6.         // For each spot in the array, pick
    7.         // a random item to swap into that spot.
    8.         for (int i = 0; i < items.Length - 1; i++)
    9.         {
    10.             int j = rand.Next(i, items.Length);
    11.             T temp = items[i];
    12.             items[i] = items[j];
    13.             items[j] = temp;
    14.         }
    15.     }
    Source: http://csharphelper.com/blog/2014/07/randomize-arrays-in-c/

    Use https://docs.unity3d.com/ScriptReference/Transform.SetSiblingIndex.html to change the Transform's child index
     
  4. begimotique

    begimotique

    Joined:
    Feb 10, 2019
    Posts:
    2
    I'm not sure about the array/list thing. That is what I have.

    The game has to be a puzzle. I put a square picture into a Picture Slicer that cuts this picture into several pieces and then insert this pieces into game object's children. The thing is that the array can be not only 3x3, but 5x5, 10x10, whatever. It will always be a square. Here is the code, maybe it will give you some information.

    Code (CSharp):
    1. void CreatePuzzle()
    2.     {
    3.         blocks = new Block[blocksPerLine, blocksPerLine];
    4.         Texture2D[,] imageSlices = ImageSlicer.GetSlices(image, blocksPerLine);
    5.         for (int y = 0; y < blocksPerLine; y++)
    6.         {
    7.             for (int x = 0; x < blocksPerLine; x++)
    8.             {
    9.                 GameObject blockObject = GameObject.CreatePrimitive(PrimitiveType.Quad);
    10.                 blockObject.transform.position = -Vector2.one * (blocksPerLine - 1) * .5f + new Vector2(x, y);
    11.                 blockObject.transform.parent = transform;
    12.  
    13.                 Block block = blockObject.AddComponent<Block>();
    14.                 block.OnBlockPressed += PlayerMoveBlockInput;
    15.                 block.OnFinishedMoving += OnBlockFinishedMoving;
    16.  
    17.                 block.Init(new Vector2Int(x, y), imageSlices[x, y]);
    18.  
    19.                 blocks[x, y] = block;
    20.          }
    21.       }
    22.    }
    23.  
     
  5. KDevS

    KDevS

    Joined:
    Dec 4, 2018
    Posts:
    7
    In the line:
    Code (CSharp):
    1. block.Init(new Vector2Int(x, y), imageSlices[x, y]);
    You can simply call a function which returns the next random value from the imageSlices array instead of manually setting the value there.

    For example, I created a simple script to simulate picking random values from a 2D array. You can use a setup similar to it:

    Code (CSharp):
    1. public class Main : MonoBehaviour
    2.     {
    3.         #region Public Fields
    4.         // 2D array of values
    5.         public int[,] ValueArray = new int[4, 4];
    6.         #endregion
    7.         //
    8.         #region Protected Fields
    9.         #endregion
    10.         //
    11.         #region Private Fields
    12.         // Random number generator
    13.         private System.Random r;
    14.         // List of unique values
    15.         private List<int> Values = new List<int>();
    16.         #endregion
    17.  
    18.         #region Unity Methods
    19.         // Use this for initialization
    20.         void Start ()
    21.         {
    22.             r = new System.Random();
    23.  
    24.             int x = ValueArray.GetLength(0);
    25.             int y = ValueArray.GetLength(1);
    26.  
    27.             for (int i = 0; i < x; i++)
    28.             {
    29.                 for (int j = 0; j < y; j++)
    30.                 {
    31.                     ValueArray[i, j] = UnityEngine.Random.Range(1, 100);
    32.                 }
    33.             }
    34.         }
    35.      
    36.         // Update is called once per frame
    37.         void Update ()
    38.         {
    39.             if (Input.GetKeyUp(KeyCode.Space))
    40.             {
    41.                 print("Next Value: " + GetNextValue());
    42.             }
    43.         }
    44.         #endregion
    45.  
    46.         #region Public Methods
    47.         #endregion
    48.         //
    49.         #region Protected Methods
    50.         #endregion
    51.         //
    52.         #region Private Methods
    53.         private int GetNextValue()
    54.         {
    55.             // limits of the 2D array
    56.             int x = ValueArray.GetLength(0);
    57.             int y = ValueArray.GetLength(1);
    58.             // range of values to randomize against
    59.             int values = x * y;
    60.             // new random index
    61.             int index = r.Next(values);
    62.             // new value
    63.             int value = ValueArray[index / x, index % y];
    64.             // check for uniqueness
    65.             if (Values.Contains(value))
    66.             {
    67.                 return GetNextValue();
    68.             }
    69.             // add the new value to the list
    70.             Values.Add(value);
    71.             // return the new value
    72.             return value;
    73.         }
    74.         #endregion
    75.     }
    In your case, the only things you will need is the Random object, the list which stores the unique values (it will be a list of Texture2D in your example) and the GetNextValue function.

    Hope that helps.
     
  6. Pawciu

    Pawciu

    Joined:
    Jun 21, 2015
    Posts:
    15
    Simple example of shuffling children in hierarchy would be calling this method on parent:


    Code (CSharp):
    1. [ContextMenu("Shuffle")]
    2.     public void Shuffle()
    3.     {
    4.         List<int> indexes = new List<int>();
    5.         List<Transform> items = new List<Transform>();
    6.         for (int i = 0; i < transform.childCount;++i)
    7.         {
    8.             indexes.Add(i);
    9.             items.Add(transform.GetChild(i));
    10.         }
    11.          
    12.         foreach (var item in items)
    13.         {
    14.             item.SetSiblingIndex(indexes[Random.Range(0, indexes.Count)]);
    15.         }
    16.     }
     
    mirtzata, FelixK-FG and SomeVVhIteGuy like this.
  7. mirtzata

    mirtzata

    Joined:
    May 9, 2019
    Posts:
    1
    man you've saved me quite a lot of work. thank you
     
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    It's good showing appreciation but in the future, please use the Like button instead of necroing old threads.

    Thanks.
     
    Bunny83 likes this.
Thread Status:
Not open for further replies.