- Home /
How to effect and apply a common material to children individually...
Hi Guys,
I'm having trouble changing the material on children inside a prefab via a raycast hit...
To set the scene I have a city that I want to be able to click on blocks and bring up a list of some sort, all in AR.
I've got everything working for the prototype aside from the "highlight"/change material.
I want to be able to highlight/change material of the block I click on/raycast hit, as well as bring up the UI details about the block/plot/gameobject.
Eventually I want to be able to bring in those details via a CSV file and update via the cloud but need the prototype up and running first.
I've got the material changing but it effects the first material slot of everything...
Eventually I want to be able to do more things with the children but will settle for understanding my problem a bit better...
As always I appreciate your time and any and all help is much appreciated.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
public class IsClicked : MonoBehaviour {
public CanvasGroup ItemCanvas;
public Renderer rend;
public Material StartColour;
public Material childColour;
public List<Transform> objects;
public List<Transform> childObjects;
public Material Glow;
List <Material> childColours;
List<Renderer> childRenderers;
Renderer childRenderer;
void Start ()
{
rend = GetComponent<Renderer>();
childColours = new List<Material>();
childRenderers = new List<Renderer>();
childRenderer = GetComponent<Renderer> ();
StartColour = childRenderer.material;
for (int i = 0; i < transform.childCount; ++i) {
childRenderers.Add (transform.GetChild (i).GetComponent<Renderer> ());
childColours.Add (childRenderers [i].material);
}
}
void Update () {
if (Input.GetMouseButtonDown (0)) {
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast (ray, out hit, 1000)) {
ItemCanvas.interactable = true;
ItemCanvas.blocksRaycasts = true;
ItemCanvas.alpha = 1;
childRenderer.material = Glow;
for (int i = 0; i < childRenderers.Count; ++i)
childRenderers [i].material = Glow;
if (hit.collider.tag == "plot_01") {
Debug.Log ("plot_01");
}
if (hit.collider.tag == "plot_02") {
Debug.Log ("plot_02");
}
if (hit.collider.tag == "plot_03") {
Debug.Log ("plot_03");
}
}
else{
Debug.Log ("you clicked on nothing");
ItemCanvas.interactable = false;
ItemCanvas.blocksRaycasts = false;
ItemCanvas.alpha = 0;
childRenderer.material = StartColour;
for(int i = 0; i < childRenderers.Count; ++i)
childRenderers[i].material = childColours[i];
}
}
}
}
Latest attempt get me the individual plots/gameobjects/blocks to change color/highlight but I can't get them back.
I know I need to store them but it doesn't seem to be working with this method.
No errors or anything.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
public class IsClicked : $$anonymous$$onoBehaviour {
public CanvasGroup ItemCanvas;
public Renderer rend;
public $$anonymous$$aterial Glow;
public GameObject Plot_01;
public Component[] allChildren;
$$anonymous$$aterial[] Originals;
$$anonymous$$aterial original$$anonymous$$at;
void Start ()
{
Plot_01 = GameObject.Find ("Plot_01");
original$$anonymous$$at = GetComponentInChildren<Renderer>().material;
}
void Update ()
{
if (Input.Get$$anonymous$$ouseButtonDown (0)) {
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast (ray, out hit, 1000)) {
ItemCanvas.interactable = true;
ItemCanvas.blocksRaycasts = true;
ItemCanvas.alpha = 1;
if (hit.collider.tag == "plot_01") {
Plot_01.GetComponent<Renderer>().material = Glow;
Debug.Log ("plot_01");
}
if (hit.collider.tag == "plot_02") {
Debug.Log ("plot_02");
}
if (hit.collider.tag == "plot_03") {
Debug.Log ("plot_03");
}
} else {
Debug.Log ("you clicked on nothing");
ItemCanvas.interactable = false;
ItemCanvas.blocksRaycasts = false;
ItemCanvas.alpha = 0;
GetComponentInChildren<Renderer>().material = original$$anonymous$$at;
}
}
}
}
O$$anonymous$$, I've got it working...kinda...
Only one of the plots changes back and forth, the others stay highlighted???
I have this on the prefab -v-
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
public class IsClicked : $$anonymous$$onoBehaviour {
public CanvasGroup ItemCanvas;
public Renderer rend;
public $$anonymous$$aterial Glow;
public Component[] allChildren;
private GameObject Plot_01;
private GameObject Plot_02;
private GameObject Plot_03;
private GameObject Plot_04;
$$anonymous$$aterial[] Originals;
$$anonymous$$aterial original$$anonymous$$at;
void Start ()
{
Plot_01 = GameObject.Find ("Plot_01");
Plot_02 = GameObject.Find ("Plot_02");
Plot_03 = GameObject.Find ("Plot_03");
Plot_04 = GameObject.Find ("Plot_04");
}
void Update ()
{
if (Input.Get$$anonymous$$ouseButtonDown (0)) {
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast (ray, out hit, 1000)) {
ItemCanvas.interactable = true;
ItemCanvas.blocksRaycasts = true;
ItemCanvas.alpha = 1;
if (hit.collider.tag == "plot_01") {
Plot_01.GetComponent<Renderer>().material = Glow;
Debug.Log ("plot_01");
}
if (hit.collider.tag == "plot_02") {
Plot_02.GetComponent<Renderer>().material = Glow;
Debug.Log ("plot_02");
}
if (hit.collider.tag == "plot_03") {
Plot_03.GetComponent<Renderer>().material = Glow;
Debug.Log ("plot_03");
}
if (hit.collider.tag == "plot_04") {
Plot_04.GetComponent<Renderer>().material = Glow;
Debug.Log ("plot_04");
}
}
else
{
Debug.Log ("you clicked on nothing");
ItemCanvas.interactable = false;
ItemCanvas.blocksRaycasts = false;
ItemCanvas.alpha = 0;
GetComponentInChildren<$$anonymous$$aterialSaver> ().Restore ();
}
}
}
}
And then this on each block/child/gameobject -v-
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
public class $$anonymous$$aterialSaver : $$anonymous$$onoBehaviour {
$$anonymous$$aterial[] original$$anonymous$$at;
void Start() {
original$$anonymous$$at = GetComponent<Renderer>().materials;
}
public void Restore() {
GetComponent<Renderer>().materials = original$$anonymous$$at;
}
}
Answer by MorphusOne1 · Aug 08, 2017 at 04:54 AM
Hey Guys,
Well that was quite fun!
I ended up doing it like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
public class IsClicked : MonoBehaviour {
public CanvasGroup ItemCanvas;
public Renderer rend;
public Material Glow;
public Material[] StartColour;
public Component[] allChildren;
private GameObject Plot_01;
private GameObject Plot_02;
private GameObject Plot_03;
private GameObject Plot_04;
List<Material> childColours;
List<Renderer> childRenderers;
Renderer parentRenderer;
void Start ()
{
childColours = new List<Material>();
childRenderers = new List<Renderer>();
parentRenderer = GetComponent<Renderer>();
StartColour = parentRenderer.materials;
for (int i = 0; i < transform.childCount; ++i)
{
childRenderers.Add(transform.GetChild(i).GetComponent<Renderer>());
childColours.Add(childRenderers[i].material);
}
Plot_01 = GameObject.Find ("Plot_01");
Plot_02 = GameObject.Find ("Plot_02");
Plot_03 = GameObject.Find ("Plot_03");
Plot_04 = GameObject.Find ("Plot_04");
}
void Update ()
{
if (Input.GetMouseButtonDown (0)) {
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 1000)) {
ItemCanvas.interactable = true;
ItemCanvas.blocksRaycasts = true;
ItemCanvas.alpha = 1;
if (hit.collider.tag == "plot_01") {
Plot_01.GetComponent<Renderer>().material = Glow;
Debug.Log("plot_01");
}
if (hit.collider.tag == "plot_02") {
Plot_02.GetComponent<Renderer>().material = Glow;
Debug.Log("plot_02");
}
if (hit.collider.tag == "plot_03") {
Plot_03.GetComponent<Renderer>().material = Glow;
Debug.Log("plot_03");
}
if (hit.collider.tag == "plot_04") {
Plot_04.GetComponent<Renderer>().material = Glow;
Debug.Log("plot_04");
}
}
else
{
Debug.Log("you clicked on nothing");
ItemCanvas.interactable = false;
ItemCanvas.blocksRaycasts = false;
ItemCanvas.alpha = 0;
parentRenderer.materials = StartColour;
for (int i = 0; i < childRenderers.Count; ++i) childRenderers[i].material = childColours[i];
}
}
}
}
If you can see a better way of doing it please let me know, alternatively if you know how I can apply a quick edit to change all the materials in every slot that would be great! otherwise I'll keep hacking away.
Thanks again!
Answer by Bill-Sansky · Aug 07, 2017 at 12:34 PM
you are changing the material of each child of your list: don't you want to change it only on the one that was hit by a raycast?
for your update, you want to have your "material saver" on each of your plot, and call them when they are not hit by the raycast anymore
Hi Bill,
Yea, I have. Only Plot_03 behaves correctly?
All the others wont return to the original material.
EDIT: Video of the Issue
Your answer
Follow this Question
Related Questions
Array of Arrays of GameObjects/Prefabs (C#) 1 Answer
Having multiple objects fire prefabs in different times C# 0 Answers
Grid Placement In Game 2 Answers
How to spawn prefab only in allowed area? 0 Answers
Change Transparency 1 Answer