- Home /
How to randomly change the color of a Shader Graph Material for only a specified GameObject, with C# script?
Hi, I'm working on a game, where the player picks up trash from Trash cans, and dumps the trash from the Trash cans into a Trash Truck. The world of the game itself is randomly generated, with randomly selected houses, with random rotations, and random Trees, Flowers, etc., etc.. I'm trying to make each one of the houses, have a randomly picked color, for each house. The problem is, I'm using a Shader Graph Material for the material of the houses, so how could I choose the random color, and for each house, not for the entire material, but just the material on each house? Also, I'm using a Vector 1 Node, plugged into the X Input Value of a Vector 2 Node, plugged into the Seed Input of a Random Range Node, which controls a Hue Node. I'm trying to control the value of the Vector 1 Node. Here's the Shader Graph Layout I have for this material:
And here's the current script I'm currently using to (try to,), control the color / Randomize the Color:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RandomHouse : MonoBehaviour
{
public GameObject[] houses;
private GameObject house;
public float[] randRots = new float[] { 0.0f, 90.0f, 180.0f, 270.0f, 360.0f };
public float timewait = 1.0f;
public RandomGen randGen;
public Material wallMat;
private Renderer renderer;
// Start is called before the first frame update
void Start()
{
RandHouse();
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.T))
{
Debug.Log("Instantiate Update!");
Destroy(house);
RandHouse();
}
}
void RandHouse()
{
int randVal = Random.Range(0, randRots.Length);
//MaterialPropertyBlock matBlock = new MaterialPropertyBlock();
//matBlock.SetFloat("Vector1_172A5ED5", Random.Range(0.0f, 360.0f));
//wallMat.SetFloat("Vector1_172A5ED5", Random.Range(0.0f, 360.0f));
house = Instantiate(houses[Random.Range(0, houses.Length)], new Vector3(0.0f, 0.0f, 0.0f), Quaternion.Euler(0.0f, randRots[randVal], 0.0f), transform);
//renderer = house.GetComponent<Renderer>();
//renderer.SetPropertyBlock(matBlock);
house.transform.localPosition = new Vector3(0.0f, 0.0f, 0.0f);
//renderer.SetPropertyBlock(matBlock);
StartCoroutine(WaitTime(timewait));
}
IEnumerator WaitTime(float wtime)
{
yield return new WaitForSeconds(wtime);
randGen.RandNew();
yield return null;
}
}
I've currently commented-out the bits of code that are supposed to make the color random / randomize the color, since it seems to break another part of my script (I think it's actually the Coroutine, now that I think about it,),.
If anyone needs any more information, please, let me know! Thanks!
Answer by Fox_GAMING · Dec 21, 2020 at 10:11 AM
Thanks for the help, everyone. I was able to reach a solution, in case anyone is wondering, here's what I did:
Here's the full, working Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RandomHouse : MonoBehaviour
{
[Header("House Prefabs")]
[Tooltip("All the Available House-Prefabs to Choose From to Randomly Generate.")]
public GameObject[] houses;
private GameObject house;
[Space]
[Header("Random Rotation Values")]
[Tooltip("All the Available Rotations to Choose From to Rotate Each House To / By.")]
public float[] randRots = new float[] { 0.0f, 90.0f, 180.0f, 270.0f, 360.0f };
[Space]
[Header("House Clone List")]
[Tooltip("A List of all of the House Clones / Randomly Spawned Houses.")]
[SerializeField] private List<GameObject> houseClone = new List<GameObject>();
[Space]
[Header("Other-Generation-Related")]
[Tooltip("Float Timewait- How long to wait before Generating new Randomly-Generated GameObjects.")]
public float timewait = 1.0f;
[Tooltip("The RandomGen Script, used to (Randomly) Generate GameObjects in each Plot.")]
public RandomGen randGen;
private Renderer renderer;
// Start is called before the first frame update
void Start()
{
//Generate House on Start.
RandHouse();
}
// Update is called once per frame
void Update()
{
//If "T" Key Pressed, Generate Again.
if (Input.GetKey(KeyCode.T))
{
//Destroy all the Old Randomly-Chosen Houses.
Debug.Log("Instantiate Update!");
Destroy(house);
houseClone.Clear();
RandHouse();
}
}
void RandHouse()
{
//Choose and Spawn a Random House.
int randVal = Random.Range(0, randRots.Length);
house = Instantiate(houses[Random.Range(0, houses.Length)], new Vector3(0.0f, 0.0f, 0.0f), Quaternion.Euler(0.0f, randRots[randVal], 0.0f), transform);
houseClone.Add(house);
//Choose a Random Color for each Randomly-Chosen House.
Renderer houserenderer = house.GetComponentInChildren<Renderer>();
foreach (GameObject house in houseClone)
{
for (int mat = 0; mat < houserenderer.materials.Length; mat++)
{
Debug.Log("Current Material: " + houserenderer.materials[mat].name);
if (houserenderer.materials[mat].name == "wall (Instance)")
{
Debug.Log("Mat Wall Found!");
MaterialPropertyBlock matBlock = new MaterialPropertyBlock();
matBlock.SetFloat("Vector1_172A5ED5", Random.Range(0.0f, 360.0f));
renderer = house.GetComponentInChildren<Renderer>();
renderer.SetPropertyBlock(matBlock, mat);
}
}
}
//Set Each Randomly-Chosen Spawned House to the Local Center.
house.transform.localPosition = new Vector3(0.0f, 0.0f, 0.0f);
StartCoroutine(WaitTime(timewait));
}
IEnumerator WaitTime(float wtime)
{
//Generate New Random GameObjects in each Plot.
Debug.Log("Start Wait Gen...");
yield return new WaitForSeconds(wtime);
Debug.Log("Wait Finished, Should be Genererating...");
randGen.RandNew();
yield return null;
}
}