BeastCoder
BeastCoder

Reputation: 2731

Instantiate A Prefab With A Random Color

Hi I've been trying to find a way to instantiate a prefab with a random color. I have looked at many questions with similar titles I'm sure they are good answers but they are not what I need. I am making a replica of a game, for practice and I want to have to random colors to be used when instantiating an object here is my code:

private Vector3 spawnPos = new Vector3(0, 0.75f, 0);
[SerializeField]
private GameObject hitCube;
private Color color1;
private Color color2;
private string lastColor;

// Use this for initialization
void Start () {
    color1 = Random.ColorHSV(0f, 1f, 0f, 0f);
    color2 = Random.ColorHSV(0f, 1f, 0f, 0f);
    for (int i = 0; i < 21; i++)
    {
        if (lastColor == "color1")
        {
            hitCube.GetComponent<Renderer>().sharedMaterial.color = color2;
            lastColor = "color2";
        }
        else
        {
            hitCube.GetComponent<Renderer>().sharedMaterial.color = color1;
            lastColor = "color1";
        }
        Instantiate(hitCube, spawnPos, Quaternion.identity);
        spawnPos.y += 0.50f;
    }

}

So does anyone know how I can make this work? When I use this the ground becomes one color and so do all of the cubes.

enter image description here

Another question I have is why does the ground change color but the launcher doesn't (it looks like it does but actually it is already set to be a darker shade of grey), and why does the ground change color in the first place? I understand that

sharedMaterial

is not the way to go because it is for all of the prefabs. All help is appreciated.

Upvotes: 1

Views: 2036

Answers (2)

BeastCoder
BeastCoder

Reputation: 2731

Wow, I'm answering my own question. But basically all you need to do is when you instantiate the cube use this code (I created it):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Cube : MonoBehaviour {

     private static Color color1;
     private static Color color2;
     private static bool hasColorsAssigned = false;
     private static string lastColor;

     // Use this for initialization
     void Start () {
         if (hasColorsAssigned == false)
         {
             color1 = new Color(Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f));
             color2 = new Color(Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f));
             hasColorsAssigned = true;
         }
         if (lastColor == "color1")
         {
             GetComponent<Renderer>().material.color = color2;
             lastColor = "color2";
         }
         else
         {
             GetComponent<Renderer>().material.color = color1;
             lastColor = "color1";
         }
 }

Then all you need to do is get rid of the coloring being used in the first script and put this onto the cube prefab.

Upvotes: 1

You have two options here:

Option 1: use multiple materials

By using sharedMaterial you're saying: "all the objects that use this material, make this change" and changing ALL the cubes to have the same color.

If you were to target .material instead, Unity will automatically clone the material and then change the new material's color.

Option 2: use a MaterialPropertyBlock

A https://docs.unity3d.com/ScriptReference/MaterialPropertyBlock.html lets you specify overrides when the renderer goes to render an object without having to create new material instances (which is slower, due to the way batching works, and uses more memory). They're pretty easy to use.

You create (or reuse) a property block, set a color on it, and then call someRenderer.SetPropertyBlock(block) and you can get a renderer by using GetComponent<Renderer>() as you're already doing.

Upvotes: 1

Related Questions