- 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