Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How do I assign random unique colors to instantiated tiles?

Discussion in 'Scripting' started by unity_3hFICh0Htpnw9Q, Jun 9, 2019.

  1. unity_3hFICh0Htpnw9Q

    unity_3hFICh0Htpnw9Q

    Joined:
    Jun 8, 2019
    Posts:
    2
    I was able to generate a set of tiles in a 3 x 3 format, as a result of using a regular nested for loop, and that works fine. However, I want to create an array of colors, and assign unique colors to each of these. I created a basic colors array and I'm able to dictate the size of it by using [SerializeField] and choosing what colors I want in the editor. However, I don't know how to have a unique color for each of my tiles specifically.

    I was thinking of using a loop to check if a color was assigned to a tile, and if so, subtract that color from the color array, and to keep assigning colors to the tiles with whatever colors remain in the array. But I don't know how this would look inside my code.

    I made a basic if statement, and I wanted to state that if a color is assigned to a tile, then subtract the array by that color (through the usage of a for loop), but I'm getting errors and I don't know what I'm doing wrong.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class GridGeneration : MonoBehaviour
    6. {
    7.     [SerializeField]
    8.     Color[] colors;
    9.  
    10.    
    11.  
    12.  
    13.     public GameObject GridTile = null;
    14.  
    15.  
    16.  
    17.     // Start is called before the first frame update
    18.     void Start()
    19.     {
    20.  
    21.         TileGenerator();
    22.  
    23.     }
    24.  
    25.  
    26.  
    27.     // Update is called once per frame
    28.     void Update()
    29.     {
    30.        
    31.     }
    32.  
    33.     void TileGenerator()
    34.  
    35.     {
    36.  
    37.         for (int i = 0; i < 3; i++)
    38.         {
    39.             for (int j = 0; j < 3; j++)
    40.             {
    41.                 GameObject Test =   Instantiate(GridTile, new Vector3(GridTile.transform.position.x * i * .25f, 1.064f, GridTile.transform.position.z * j * .25f), Quaternion.identity);
    42.                 Test.GetComponent<MeshRenderer>().material.color = colors[Random.Range(0, colors.Length)];
    43.                 if(Test = Colors[i] colors)
    44.                 {
    45.  
    46.                         Colors[] colors = Colors[] colors - Colors[i] colors;
    47.  
    48.                 }
    49.             }
    50.  
    51.  
    52.  
    53.         }
    54.  
    55.     }
    56. }
    57.  
     
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,186
    Personally, depending on the use case, I would either simply remove the color from a list once it's been assigned, or, if I needed to recycle the list, then move the used ones to a second list of used colors, then add them back to the main list once I needed the full list again.
     
  3. SparrowGS

    SparrowGS

    Joined:
    Apr 6, 2017
    Posts:
    2,536
    or have it saved as an array, don't touch the array to keep it perfectly safe and when you need to assign colors make a temporary list out of that array and do what you said with it, then just dump it.

    besides this, this is my solution as well.
     
  4. unity_3hFICh0Htpnw9Q

    unity_3hFICh0Htpnw9Q

    Joined:
    Jun 8, 2019
    Posts:
    2
    I'm confused on how to write the temporary list within my Unity code though. I'm assuming that I would need to write an if statement, where if a color is assigned to a tile, then make a temporary list using a for loop, and choose a random color from there? I feel like I'm confusing myself thinking about this.
     
  5. SparrowGS

    SparrowGS

    Joined:
    Apr 6, 2017
    Posts:
    2,536
    Code (CSharp):
    1. Color[] allColors;
    2. List<Color>tempColors;
    3.  
    4. public void Init(){
    5.    RefreshColorList();
    6. }
    7.  
    8. public Color GetRandomColor(){
    9.    Color selectedColor = tempColors[Random.Range(0, tempColor.Length)];
    10.    tempColors.Remove(selectedColor);
    11.    return selectedColor;
    12. }
    13.  
    14. public void RefreshColorList(){
    15.    tempColors = allColors.ToArray();
    16. }
    "GetRandomColor" could be optimized, but you get the point.
    you have an array the hold all the colors (the obviously named and only color array in the code), you copy that into a list (why a list you ask? because it's much easier to Add and Remove from a list, it's basically a front for an array with handy functions), when you need a color you pull a random one off the list (or you could shuffle it in advance and just pull the first one) and remove it from the list eliminating the possibility to get the same one in a row(unless you had 2 of the same in the original list, you can't get the same element with this).
     
  6. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    In SparrowsNest's example above, I believe
    tempColors = allColors.ToArray();

    should instead be
    tempColors = allColors.ToList();

    since tempColors is a list, not an array.

    Also, minor note, but: Removing from the list could be optimized. For one thing, since you are generating an index, you can remove using RemoveAt() instead of Remove(), and then the List doesn't need to search for the item before removing it. But since the order of your list doesn't matter, it would be even better to swap the element being removed with the last element and then remove that. (Removing from the end of a list is O(1) but removing from the middle is O(N) because the List has to shift all the remaining elements forward one-at-a-time to preserve their order.)

    Code (CSharp):
    1.     // O(1)
    2.     public static void RemoveBySwap<T>(this List<T> list, int index)
    3.     {
    4.         list[index] = list[list.Count - 1];
    5.         list.RemoveAt(list.Count - 1);
    6.     }
     
    SparrowGS likes this.