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
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Material Keywords applied in script are reset when Material is viewed in Inspector.

Discussion in 'Scripting' started by RedVonix, Apr 27, 2022.

  1. RedVonix

    RedVonix

    Joined:
    Dec 13, 2011
    Posts:
    414
    Looks like another Unity bug, but want to verify it before I report.

    In my script, I do the following to enable Emission on a material (specifically, the Universal Render Pipeline/Lit material):

    Code (CSharp):
    1. myMaterial.EnableKeyword("_EMISSION");
    And this works - in the scene, I can see that the Emission is enabled. I can save the scene, leave the scene and return to the scene, and the Emission property looks great. However, if I click on the Material and view it in the inspector - the _EMISSION keyword is immediately disabled, and the Material loses it's emission.

    My expectation here would be that when opening a Material in the Inspector, it does not change the keywords.

    Is there something I'm missing, perhaps an Apply method of some sort?

    Thank you!
     
    kana1939 likes this.
  2. Peeling

    Peeling

    Joined:
    Nov 10, 2013
    Posts:
    404
    I suspect the 'bug' is that the emission setting is persisting as long as it is.

    Keywords don't actually 'exist'. They're the direct analog of compiler switches like #if and #else. Unity will compile each variant on demand (that's why you sometimes see flashes of blue for a while after you've edited a shader).

    When you enable a keyword, you're actually telling Unity to rummage around and find the version of the shader that it compiled with that keyword enabled, and use it instead. But that switch is not connected back to the property in the material that told Unity which to use by default.

    If you want to make a permanent change, that might be possible if you can talk directly to the material and set the property, rather than talking to Unity's renderer and 'enabling a keyword'. Then it should work like other persistent properties of a material you set from script
     
  3. RedVonix

    RedVonix

    Joined:
    Dec 13, 2011
    Posts:
    414
    In my case, I'm actually creating the material, setting the properties, and then saving it to disk, like so:

    Code (CSharp):
    1. Material newMaterial = new Material();
    2.  
    3. newMaterial.SetTexture("_EmissionMap", emissionTexture);
    4. newMaterial.EnableKeyword("_EMISSION");
    5.  
    6. AssetDatabase.CreateAsset(newMaterial, materialPath);
    7. AssetDatabase.SaveAssets();
    8. AssetDatabase.Refresh();
    Wouldn't this be directly talking to the material?
     
  4. Peeling

    Peeling

    Joined:
    Nov 10, 2013
    Posts:
    404
    Try "SetKeyword" rather than "EnableKeyword"; I think that might be what you are looking for.
     
  5. Mirror_Shiel

    Mirror_Shiel

    Joined:
    Jan 23, 2019
    Posts:
    5
    Did you ever figure out a fix or workaround for this issue? Seems I'm having about the same one. My normal material properties are being properly overwritten, but my feature keywords are being reset to the value they were set to in the Material inspector.
     
  6. Twoseven

    Twoseven

    Joined:
    Jul 13, 2016
    Posts:
    3
    I would love to know if there is a workaround for this too!
     
  7. Twoseven

    Twoseven

    Joined:
    Jul 13, 2016
    Posts:
    3
    I worked this out @Mirror_Shiel, @RedVonix
    You need to have a variable inside the shader to mirror the keyword feature
    eg:

    properties
    {
    [Toggle(VERTEX_LIGHT)] VERTEX_LIGHT("Has Baked Vertex Shadows", Float) = 0.0
    }
    ...
    #pragma multi_compile _ VERTEX_LIGHT_ON
    ...
    float VERTEX_LIGHT; //preserves the material after editor reload
     
  8. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,268
    Currently my solution is to open the material file and set the keyword's value to 1. Obviously not fun, but it does work.