Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Resolved HDRP material instance does not affect the mesh renderer it is attached to

Discussion in 'General Graphics' started by Haniasita, Mar 17, 2023.

  1. Haniasita

    Haniasita

    Joined:
    Oct 4, 2018
    Posts:
    3
    Hello everyone! I've been searching for a solution to this problem for several hours now to no avail; so here goes.

    Long story short : During runtime, two types of material instances (car tail lights & brake lights) do not affect the look of the mesh they are attached to, despite visibly being updated when seen from the inspector. This ONLY happens after entering Play Mode for a second time. Restarting the Editor fixes this for exactly one Play Mode entry.

    Now for the full scope of the issue. I'm working on a semi-realistic car simulation for a co-op open-world game, where cars are built out of individual pieces that may be swapped or broken off.

    When taillights are installed onto the car, the following is run to register relevant materials :

    Code (CSharp):
    1. [NonSerialized] public Material tail;
    2. [NonSerialized] public Material brake;
    3.  
    4. /* etc.. */
    5.  
    6. MeshRenderer renderer = instance.GetComponent<MeshRenderer>();
    7. for (int i = 0; i < renderer.materials.Length; i++)
    8. {
    9.     if (renderer.materials[i].name == "Tail (Instance)") { tail = renderer.materials[i]; continue; }
    10.     if (renderer.materials[i].name == "Brake (Instance)") { brake = renderer.materials[i]; continue; }
    11. }
    12.  
    Then, in the car simulation, the following is run on FixedUpdate to control the value of emission from these materials :

    Code (CSharp):
    1.  
    2. l_BrakeFactor = Mathf.SmoothStep(l_BrakeFactor, l_BrakeOn ? 100000f : 0f, 0.25f);
    3. l_LowBeamsFactor = Mathf.SmoothStep(l_LowBeamsFactor, l_LowBeamsOn ? 100000f : 0f, 0.25f);
    4.  
    5. /* etc */
    6.  
    7. Taillights.brake.SetColor("_EmissiveColor", Color.red * l_BrakeFactor);
    8. Taillights.tail.SetColor("_EmissiveColor", Color.red * l_LowBeamsFactor);
    Headlights work the same exact way and function perfectly fine most of the time. On very rare occasion, they will show the same signs. The emission of tail & brake lights, on the other hand, gets consistently stuck after entering play mode for a second time.

    Here is what happens after restarting the Editor and entering Play Mode for the first time :

    This is expected behaviour.

    Here is what happens upon entering Play Mode a second time, and every time thereafter until a restart :

    You can see in the inspector that the material is indeed updating, it's just not showing on the mesh itself. Modifying the material trough the inspector does nothing. The brake light material was made intentionally bright in this case to demonstrate the issue. If things were functioning properly, the brake light would turn off.

    I've checked everything from the mesh itself to debug logging the color value from the material instance, and by all means everything seems fine beyond this one problem. I've also tried a couple hacks I found online, to no avail. I've just about exhausted all ideas I had, and Google isn't being helpful.

    I'm using Unity 2022.2.11f1, and have tried with 2021.3.16f1 aswell, yielding the same results.
    My rig has an RTX 2070 with driver version 531.29 (latest at the time of writing).
    My rendering API is set to DirectX 12.

    Any feedback would be greatly appreciated, thank you.
     
    Last edited: Mar 18, 2023
  2. Haniasita

    Haniasita

    Joined:
    Oct 4, 2018
    Posts:
    3
    I've made the following script to test emission in my project, and this works perfectly every time :

    Code (CSharp):
    1. public class EmissionTester : MonoBehaviour
    2. {
    3.     [NonSerialized] public Material mat;
    4.     private float time = 0f;
    5.     private float timeMax = 1f;
    6.     private float factor = 0f;
    7.     // Start is called before the first frame update
    8.     void Start()
    9.     {
    10.         MeshRenderer renderer = GetComponent<MeshRenderer>();
    11.         for (int i = 0; i < renderer.materials.Length; i++)
    12.         {
    13.             if (renderer.materials[i].name == "Brake (Instance)") { mat = renderer.materials[i]; continue; }
    14.         }
    15.     }
    16.  
    17.     // Update is called once per frame
    18.     void FixedUpdate()
    19.     {
    20.         time += Time.deltaTime;
    21.         if (time > timeMax) time = 0f;
    22.  
    23.         factor = Mathf.SmoothStep(factor, time * 100000f, 0.25f);
    24.         mat.SetColor("_EmissiveColor", Color.red * factor);
    25.     }
    26. }
    My guess is then that something inside my code must be broken, rather than this being a Unity glitch. I'll report back if I find what the problem is.
     
  3. Haniasita

    Haniasita

    Joined:
    Oct 4, 2018
    Posts:
    3
    What I thought was a visual glitch turned out to be an error in my code. The reference for the taillight materials would get overwritten on spawn by a different section of my code, thus making my code update an instance of the material that does not actually exist.

    Very strange nevertheless that this ghost instance of the material would show up when selecting the taillights, but it's fixed and that's all that matters.

    Thank you for anyone who read trough the thread, and I apologize for blaming Unity for something that was my fault.