CLONING COLORS QUEST: ‘Spawn A Random Colored Block’ - Solutions

Quest: Cloning Colors Quest
Challenge: Spawn A Random Colored Block

Feel free to share your solutions, ideas and creations below. If you get stuck, you can find some ideas here for completing this challenge.

Ok so I spent almost an entire day tring to figure the solution for this challenge, and when I did found the solution I was very happy.
I also had to change the ColorChanger class from the first challenge a bit.
So this is my solution

That’s the new ColorChanger class

using UnityEngine;

public class ColorChanger : MonoBehaviour
{
    public SpriteRenderer mySpriteRenderer;
    [HideInInspector] public Color color;
    public colorChangeEnum colors;
    void Awake()
    {
        mySpriteRenderer = GetComponent<SpriteRenderer>();
    }

    private void Start()
    {
        switch (colors)
        {
            case colorChangeEnum.red:
                color = Color.red;
                break;
            case colorChangeEnum.blue:
                color = Color.blue;
                break;
            case colorChangeEnum.yellow:
                color = Color.yellow;
                break;
        }
        mySpriteRenderer.color = color;
    }
}
public enum colorChangeEnum
{
    red, yellow, blue
}

And this is the SpawnNewBlock class. After I Instantiate the block game object I find the ColorChanger class, and then I randomize the colors for the block

Edit: I changed the SpawnNewBlock because I had a bug where if there are no active blocks and you spawn a new one, it will not be active, so I added an if statement

using UnityEngine;

public class SpawnNewBlock : MonoBehaviour
{
    [SerializeField] Transform spawnPosition;
    private ColorChanger colorChanger;
    [SerializeField] private GameHandler gameHandler;
    private BlockMovement blockMovement;

    public void SpawnBlock(GameObject block)
    {
        block = Instantiate(block, spawnPosition.position, Quaternion.identity) as GameObject;
        colorChanger = FindObjectOfType<ColorChanger>();
        if(gameHandler.allPlayerBlocks.Length == 0)
        {
            blockMovement = FindObjectOfType<BlockMovement>();
            blockMovement.isActiveBool = true;
        }

        block.gameObject.GetComponent<SpriteRenderer>().color = colorChanger.color;
        colorChanger.colors = (colorChangeEnum)Random.Range(0, 3);
    }
}

It took me some time to find out how to link all available colors to the instantiated gameObject.

Because i am using a slider, which gives me “int” but a fast way to change colors with the inspector, I had to link the int values to the corresponding colors.

We have a prefab to be instantiated and a spawnposition.

    [SerializeField] GameObject blockPrefab;
    [SerializeField] Transform spawnPosition;
    private Color[] _colors;

The Color Changer has all available colors, we are getting them aswell.

private void Awake()
{
    // get all colors, to chose from
    _colors = blockPrefab.GetComponent<ColorChanger>().GetAvailableColor;
}

The new Block used our own Method to change its color

    public void SpawnBlock()
    {
        ChangeColor();
        Instantiate(blockPrefab, spawnPosition.position, Quaternion.identity);
    }

Because we have an int value (used for Random), we can choose any and use it for the “setter” to change ChosenColor.

private void ChangeColor()
{
    // we know the size of our available colors
    var index = Random.Range(0, _colors.Length);
    // the setter inside the prefab, lets us change its value
    blockPrefab.GetComponent<ColorChanger>().SetChosenColor = index;
}

Reference to : ColorChanger Script

public int SetChosenColor { set => chosenColor = value; }

Another refactor and this is a big one with a lot of changes from the old code.
Every time I click on the spawn button I create a random int and it’s assigned to one of the colors in the enum

using UnityEngine;

public class SpawnNewBlock : MonoBehaviour
{
    [SerializeField] GameObject blockPrefab;
    [SerializeField] Transform spawnPosition;

    private int randColor;

    public void SpawnBlock()
    {
        randColor = Random.Range(0, 3);
        // assigning random int that represent the enum index
        blockPrefab.GetComponent<ColorChanger>().colors = (ColorSelect)randColor;
        Instantiate(blockPrefab, spawnPosition.position, Quaternion.identity);
    }
}
1 Like

I usually change the variables of the gameobject after it has been instantiated rather than the prefab itself but I assume yours is working OK though not sure what happens if other things are using the prefab…

Instead of hardcoding 3 try using
System.Enum.GetValues(typeof(ColorSelect)).Length
which gets the number of colors in the Enum so if you add colors to the Enum you wont need to change the code.

3 Likes

Yep you’re correct. I acctualy changed this class after I post it and created a new gameobject before instantiate it

Quick one for me. Created a public method for assigning a random colour in ColorChanger:

public void SetRandomColour()
{
    mySpriteRenderer.color = colours[Random.Range(0, 3)];
}

Then modified the spawnblock method to call it.

public void SpawnBlock()
{
    GameObject newBlock = Instantiate(blockPrefab, spawnPosition.position, Quaternion.identity);
    newBlock.GetComponent<ColorChanger>().SetRandomColour();
}
2 Likes

SpriteColors is a public enum in the ColorChanger.

In SpawnBlock:

 public void SpawnBlock()
    {
        GameObject block = Instantiate(blockPrefab, spawnPosition.position, Quaternion.identity);
        
        int randomColor = Random.Range(0, System.Enum.GetNames(typeof(SpriteColors)).Length);

        block.GetComponent<ColorChanger>().colorSelection = (SpriteColors)randomColor;
    }

Privacy & Terms