Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question GameObject Material change is not working

Discussion in 'Scripting' started by usernotauser, Jan 16, 2023.

  1. usernotauser

    usernotauser

    Joined:
    Nov 6, 2021
    Posts:
    12
    Hi everyone, so I've written the script to highlight the selected GameObject on MouseButtonDown. The idea is that when ray hits the object, the color of each of the object's materials is changed (void SelectionHighlight). When the other object is hit, the previous object has to get its original materials back (void SelectionHighlightBack) in the right order and the newly hit object has its materials color-changed.
    The mesh, containing the materials is each GameObject's child.

    The SelectionHighlight works well, the materials change their color. However, when other GameObject is selected, the previous one still has its materials' color changed and not returned to the oriignal ones.

    I've been trying to find the cause for this for days, and have no other idea what's going wrong. I would appreciate if someone could point to the possible cause. Thanks in advance!



    Important remark: each object has 3 materials assigned to it. The materials' assignment order is random for every object.

    Here is the script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System.Linq;
    5.  
    6. public class ObjectClicker : MonoBehaviour
    7. {
    8.  
    9.     private Address address_bldg;
    10.     public GameObject bldg;
    11.     public GameObject bldg1;
    12.     private string bldg_city;
    13.     private string bldg_street;
    14.     private string bldg_house;
    15.     public string selected;
    16.     public string select;
    17.     public GameObject bldgOrig;
    18.  
    19.  
    20.     Renderer rend;
    21.     ColorChange clrChange;
    22.    
    23.     // Update is called once per frame
    24.     private void Update()
    25.     {
    26.         if (Input.GetMouseButtonDown(0))
    27.         {
    28.             RaycastHit hit;
    29.             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    30.  
    31.             if (Physics.Raycast(ray, out hit, 100.0f))
    32.             {
    33.  
    34.                 if (hit.transform != null)
    35.                 {
    36.                     bldg = hit.transform.parent.gameObject;
    37.              
    38.                     select = bldg.name;
    39.  
    40.                     if(string.IsNullOrEmpty(selected))
    41.                     {
    42.                        
    43.                         address_bldg = bldg.GetComponent<Address>(); //getting the address script from the building object
    44.                         bldg_city = address_bldg.City;
    45.                         bldg_street = address_bldg.Street;
    46.                         bldg_house = address_bldg.HouseNumber;
    47.  
    48.                         TooltipManager._instance.SetAndShowToolTip(bldg_city, bldg_street, bldg_house);
    49.  
    50.                         selected = bldg.name;
    51.  
    52.                         // getting the mesh from the building object (its child)
    53.                         Transform bldgChild = bldg.transform.GetChild(0);
    54.                         // getting the materials from this mesh to list
    55.                         List<Material> materialsBldgOrig = bldgChild.GetComponent<Renderer>().materials.ToList();
    56.                         // highlighting the building
    57.                         SelectionHighlight(bldgChild);
    58.                     }
    59.                     else if(selected != select && string.IsNullOrEmpty(selected) == false)
    60.                     {
    61.                         address_bldg = bldg.GetComponent<Address>(); //getting the address script from the building object
    62.                         bldg_city = address_bldg.City;
    63.                         bldg_street = address_bldg.Street;
    64.                         bldg_house = address_bldg.HouseNumber;
    65.  
    66.                         // changing colour of the previously selected building
    67.                         bldgOrig = GameObject.Find(selected);
    68.                         //Debug.Log(bldgOrig.name);
    69.                         Transform bldgChildChanged = bldgOrig.transform.GetChild(0);
    70.                         // getting the materials from this mesh to list
    71.                         List<Material> materialsBldgOrig = bldgChildChanged.GetComponent<Renderer>().materials.ToList();
    72.  
    73.                         SelectionHighlightBack(bldgChildChanged, materialsBldgOrig);
    74.                        
    75.                         selected = bldg.name;
    76.  
    77.                         // getting the mesh from the building object (its child)
    78.                         Transform bldgChild = bldg.transform.GetChild(0);
    79.                        
    80.  
    81.                         SelectionHighlight(bldgChild);
    82.  
    83.                         TooltipManager._instance.SetAndShowToolTip(bldg_city, bldg_street, bldg_house);
    84.                     }
    85.                    
    86.  
    87.                 }
    88.                 else
    89.                 {
    90.                     TooltipManager._instance.HideToolTip();
    91.                 }
    92.             }
    93.         }
    94.        
    95.     }
    96.  
    97.  
    98.     void SelectionHighlight(Transform bldg)
    99.     {
    100.         List<Material> materialsBldg = bldg.GetComponent<Renderer>().materials.ToList();
    101.  
    102.         foreach(Material mat in bldg.GetComponent<Renderer>().materials)
    103.         {
    104.             mat.color = new Color32(100, 50, 230, 255);
    105.         }
    106.     }
    107.  
    108.     // this method gets the list of materials for the selected building and changes colours back
    109.     // List mats is the list of the original materials
    110.     void SelectionHighlightBack(Transform bldgChanged, List<Material>matsOriginal)
    111.     {
    112.         // getting materials (chenged) of the building
    113.         Material[] materialsBldg = bldgChanged.GetComponent<Renderer>().materials;
    114.  
    115.         for (int i = 0; i < 3; i++)
    116.         {
    117.            
    118.             materialsBldg[i] = matsOriginal[i];
    119.            
    120.         }
    121.  
    122.         bldgChanged.GetComponent<Renderer>().materials = materialsBldg;
    123.     }
    124.  
    125.    
    126. }
    127.  
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,947
    That's a complex blob of code to just stare at but I'll speculate that you're probably modifying copies of the Materials when you think you're modifying the actual ones.

    Simplify it... the "auto-instantiate-ness" of Materials can be tricky. Make a small blob of code to set each condition (selected or not) and then put the two calls into an endless Coroutine that does one, waits a second, does the other, waits a second, and back and forth endlessly until you have that working 100% solidly.

    There is also a .sharedMaterials array you can access as well, and also this general blurb, which I think you are already aware of based on your code above:

    Materials materials array of materials renderer:

    https://forum.unity.com/threads/cha...as-working-now-it-is-not.883372/#post-5923346

    https://forum.unity.com/threads/adding-and-removing-a-material-at-runtime.1048649/#post-6783635
     
    usernotauser likes this.
  3. usernotauser

    usernotauser

    Joined:
    Nov 6, 2021
    Posts:
    12
    Okay, now I finally fixed it.

    So here's what I did. The major change is the void SelectionHighlight. It follows the same logic as the material returning method SelectionHighlightBack.

    Code (CSharp):
    1. void SelectionHighlight(Transform bldg, Material selectionMaterial)
    2.     {
    3.         Material[] materialsBldg = bldg.GetComponent<Renderer>().materials;
    4.  
    5.         for (int i = 0; i < 3; i++)
    6.         {
    7.             materialsBldg[i] = selectionMaterial;
    8.         }
    9.  
    10.         bldg.GetComponent<Renderer>().materials = materialsBldg;
    11.     }

    I then added public Material selectionMaterial into the code and changed method calls so they call selectionMaterial method and submit selectionMaterial variable to it.