Search Unity

Bug Material isn't updated in Editor

Discussion in 'High Definition Render Pipeline' started by Rowlan, Aug 3, 2020.

  1. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,300
    I create a gameobject with an instanced material (hdrp/lit and transparent surface type) and assign the material. However, the modified material properties (compared to standard which is opaque) are only applied when I expand the material in the inspector.

    How do you refresh the material / scene so that everything is up to date?

    I tried EditorUtility.SetDirty and EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()) but nothing seemed to work.

    Screenshots:

    Gameobject and material creation. The grey rectangle should be transparent:

    m1.png

    The material inspector is collapsed

    m2.png

    Now I click the expand icon:

    m3.png

    And all of a sudden the grey area has become transparent:

    m4.png

    What happens on the expanding of the material inspector that I need to apply?
     
  2. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,555
    Do you have "Always Refresh" checked (above scene view)?
    always_refresh.jpg
     
    lucvw_1975 likes this.
  3. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,300
    I don't have that option in 2020.1.0f1:

    ar.png
     
  4. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,555
    I think Always Refresh is the same as Animated Materials - if you have that checked, does the problem persist?
     
  5. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,300
    Yeah, tried it, didn't help.
     
  6. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,300
    I created a quick reproduction case which creates 2 spheres with materials. One Opaque, the other Transparent:

    Code (CSharp):
    1.  
    2. using UnityEditor;
    3. using UnityEditor.SceneManagement;
    4. using UnityEngine;
    5.  
    6. public class MaterialTest : MonoBehaviour
    7. {
    8.     [MenuItem("MaterialTest/Create", false, 10)]
    9.     static void CreateCustomGameObject(MenuCommand menuCommand)
    10.     {
    11.         CreateOpaqueSphere();
    12.         CreateTransparentSphere();
    13.     }
    14.  
    15.     static void CreateOpaqueSphere()
    16.     {
    17.         GameObject go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    18.         go.name = "Opaque Sphere";
    19.         go.transform.position = new Vector3(0, 0, 0);
    20.  
    21.         var unityMaterial = new UnityEngine.Material(Shader.Find("HDRP/Lit"));
    22.  
    23.         unityMaterial.SetFloat("_SurfaceType", 0); // 0 = Opaque; 1 = Transparent
    24.         unityMaterial.SetFloat("_Metallic", 1f);
    25.         unityMaterial.SetFloat("_Smoothness", 1f);
    26.  
    27.         unityMaterial.renderQueue = -1;
    28.  
    29.         go.GetComponent<Renderer>().sharedMaterial = unityMaterial;
    30.  
    31.         EditorUtility.SetDirty(go);
    32.         EditorUtility.SetDirty(unityMaterial);
    33.         EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
    34.     }
    35.  
    36.     static void CreateTransparentSphere()
    37.     {
    38.         GameObject go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    39.         go.name = "Transparent Sphere";
    40.         go.transform.position = new Vector3(2, 0, 0);
    41.  
    42.         var unityMaterial = new UnityEngine.Material(Shader.Find("HDRP/Lit"));
    43.  
    44.         unityMaterial.EnableKeyword("_BLENDMODE_PRESERVE_SPECULAR_LIGHTING");
    45.         unityMaterial.EnableKeyword("_BLENDMODE_PRE_MULTIPLY");
    46.         unityMaterial.EnableKeyword("_ENABLE_FOG_ON_TRANSPARENT");
    47.         unityMaterial.EnableKeyword("_NORMALMAP_TANGENT_SPACE");
    48.         unityMaterial.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
    49.  
    50.         unityMaterial.SetColor("_BaseColor", new Color(128, 0, 0, 0f));
    51.         unityMaterial.SetFloat("_SurfaceType", 1); // 0 = Opaque; 1 = Transparent
    52.         unityMaterial.SetFloat("_Metallic", 1f);
    53.         unityMaterial.SetFloat("_Smoothness", 1f);
    54.  
    55.         unityMaterial.renderQueue = 3000;
    56.  
    57.         go.GetComponent<Renderer>().sharedMaterial = unityMaterial;
    58.  
    59.         EditorUtility.SetDirty(go);
    60.         EditorUtility.SetDirty(unityMaterial);
    61.         EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
    62.     }
    63. }
    64.  
    In the main menu click MaterialTest -> Create. You'll get this:

    s1.png
    As soon as you open the material of the Transparent Sphere in the inspector nothing happens in opposite to the above mentioned bug description. But when I edit the color and set the transparency value to the same value, it starts to look like it should:

    s2.png

    Something I'm missing, I just don't know what.
     
    Ruchir likes this.
  7. Shaunyowns

    Shaunyowns

    Joined:
    Nov 4, 2019
    Posts:
    328
    Hey Rowlan, I can send this post over, if you think this is a bug please report it as well - https://unity3d.com/unity/qa/bug-reporting
     
  8. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,300
    Awesome, I created one, thank you very much! Ticket number is 1268504

    By the way, I dug through the hdrp code and it appears that some reset is happening there that I'm missing. I tried almost everything in there, but yet didn't find a solution. It shouldn't even be needed imo. Problem is also I have no access to e. g. ApplyKeywordsAndPassesIfNeeded which seems to be used in the material inspector of LitGUI.cs to fix the material:

    Code (CSharp):
    1.         protected void ApplyKeywordsAndPassesIfNeeded(bool changed, Material[] materials)
    2.         {
    3.             // !!! HACK !!!
    4.             // When a user creates a new Material from the contextual menu, the material is created from the editor code and the appropriate shader is applied to it.
    5.             // This means that we never setup keywords and passes for a newly created material. The material is then in an invalid state.
    6.             // To work around this, as the material is automatically selected when created, we force an update of the keyword at the first "frame" of the editor.
    7.  
    8.             // Apply material keywords and pass:
    9.             if (changed || m_FirstFrame)
    10.             {
    11.                 m_FirstFrame = false;
    12.  
    13.                 foreach (var material in materials)
    14.                     SetupMaterialKeywordsAndPassInternal(material);
    15.             }
    16.         }
    I also saw this necessary:

    Code (CSharp):
    1.         // This is a hack for GI. PVR looks in the shader for a texture named "_MainTex" to extract the opacity of the material for baking. In the same manner, "_Cutoff" and "_Color" are also necessary.
    2.         // Since we don't have those parameters in our shaders we need to provide a "fake" useless version of them with the right values for the GI to work.
    3.         public static void SetupMainTexForAlphaTestGI(this Material material, string colorMapPropertyName, string colorPropertyName)
    4.         {
    5.             if (material.HasProperty(colorMapPropertyName))
    6.             {
    7.                 var mainTex = material.GetTexture(colorMapPropertyName);
    8.                 material.SetTexture("_MainTex", mainTex);
    9.             }
    10.  
    11.             if (material.HasProperty(colorPropertyName))
    12.             {
    13.                 var color = material.GetColor(colorPropertyName);
    14.                 material.SetColor("_Color", color);
    15.             }
    16.  
    17.             if (material.HasProperty("_AlphaCutoff")) // Same for all our materials
    18.             {
    19.                 var cutoff = material.GetFloat("_AlphaCutoff");
    20.                 material.SetFloat("_Cutoff", cutoff);
    21.             }
    22.         }
    which is used for

    Code (CSharp):
    1.             material.SetupMainTexForAlphaTestGI("_BaseColorMap", "_BaseColor");
    2.  
    I left the example code simple nontheless because neither of those above solved it.

    But I can't tell if that's even the part that refreshes the material in the end.

    If there is no other solution the main goal would be to explicitly invoke some kind of fix / refresh on a material to force the editor to look exactly like the build.
     
    Last edited: Aug 5, 2020
  9. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,300
    @Shaunyowns I found the problem with the color, it was actually a noob mistake. I'm importing values from an external interface which are color values from 0-255. But Unity uses 0-1.

    However transparency is only updated when i open the material in the material inspector and click the arrow down, i. e. I'm back to the problem in the initial post.
     
    Last edited: Aug 6, 2020
  10. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,300
    @Shaunyowns Got it now. ZWrite wasn't set to 10.

    I simply did a comparison of the properties using a script I made, i. e. compared what I created to what the material inspector fixed. It would still be preferred to have some kind of utility method that fixed a material.

    How can I close the ticket?

    Thank you very much!
     
    Last edited: Aug 6, 2020
  11. Tbarthelemy

    Tbarthelemy

    Joined:
    Aug 26, 2019
    Posts:
    6
    Hello @Rowlan , sorry to bother you, I have a similar problem with a new plugins I'm using.
    From what I saw the plugin use a created shader from shader graph, but when it generates the material (all the gameobject are generated at play) it seems like the transparent settings aren't correctly set, until I open it from inspector. What did you change to make it work ?
     
  12. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,300
    The problem is that Unity fixes missing material settings implicitly when you expand the material settings in the inspector. That's super bad, one can never find errors this way. What I did was compare the material settings before and after I opened it in the inspector and then I added the missing parts in my code. However since you say you use shader graph, it should work out of the box. My problem was just for the case when I changed material settings via code.
     
  13. Tbarthelemy

    Tbarthelemy

    Joined:
    Aug 26, 2019
    Posts:
    6
    Oh okay ! Yeah the shader in itself seems fine since I don't modify it, but in play it just seems like I need to refresh it because it disable Keyword or properties.

    Thx for the quick answer ;).
     
  14. freyabee

    freyabee

    Joined:
    Mar 21, 2018
    Posts:
    3
    I have the same issue with changing transparency mode and it not updating until clicking the material in inspector. Glad I'm not the only one.
     
  15. GXMark

    GXMark

    Joined:
    Oct 13, 2012
    Posts:
    515
    I also have this same bug and its really not possible to fix unless unity finds a way to update their material for a transparent surface type. This is actually a major bug and should be fixed. I also know this problem has been around for years and nothing has been done about it.


    One recommendation i would suggest would be to define your material surface types as material templates in the project. Then use the resource.load technique and cache them on start-up. This is obviosly a good approach if you dont have many permutations of keywords your working with. I still not tested if this corrects the editor material instancing issue but worth a try. [ WORKS FINE, JUST TESTED ]

    For example
    Code (CSharp):
    1.             _materials = new Dictionary<string, Material>();
    2.             _materials.Add(HDRP_UNLIT_OPAQUE, Resources.Load<Material>(matTemplatePath + HDRP_UNLIT_OPAQUE));
    3.             _materials.Add(HDRP_UNLIT_OPAQUE_DOUBLE, Resources.Load<Material>(matTemplatePath + HDRP_UNLIT_OPAQUE_DOUBLE));
    4.             _materials.Add(HDRP_UNLIT_TRANS, Resources.Load<Material>(matTemplatePath + HDRP_UNLIT_TRANS));
    5.             _materials.Add(HDRP_UNLIT_TRANS_DOUBLE, Resources.Load<Material>(matTemplatePath + HDRP_UNLIT_TRANS_DOUBLE));
    6.             _materials.Add(HDRP_LIT_OPAQUE, Resources.Load<Material>(matTemplatePath + HDRP_LIT_OPAQUE));
    7.             _materials.Add(HDRP_LIT_OPAQUE, Resources.Load<Material>(matTemplatePath + HDRP_LIT_OPAQUE_DOUBLE));
    8.             _materials.Add(HDRP_LIT_TRANS, Resources.Load<Material>(matTemplatePath + HDRP_LIT_TRANS));
    9.             _materials.Add(HDRP_LIT_TRANS_DOUBLE, Resources.Load<Material>(matTemplatePath + HDRP_LIT_TRANS_DOUBLE));
     
    Last edited: Jun 15, 2021
    Ruchir likes this.
  16. GXMark

    GXMark

    Joined:
    Oct 13, 2012
    Posts:
    515
    Quick update on my last post which works in HDRP

    HDRP stores all its rendering setup in the material properties

    This function will ensure that our material is always using the correct keyword setup for those properties.

    #if UNITY_EDITOR
    HDShaderUtils.ResetMaterialKeywords(materials[j]);
    #endif
     
    RunBust and Ruchir like this.
  17. M-Elwy

    M-Elwy

    Joined:
    Jan 28, 2021
    Posts:
    38
    I tried @Rowlan script, unfortunately it didn't find any difference, I tried to reset material keywords
    @GXMark That FIXED my issue, thank you sir.
     
  18. n_mejia

    n_mejia

    Joined:
    Apr 19, 2022
    Posts:
    1
    This works as long as you are in the editor, for a release build it doesn't since it needs to be running on the editor. Has anyone find a way to reset the material keywords on a build? I do fbx and material setup at runtime, tried taking notes on the shader keywords after the reset on the editor and forcing them on material.EnableKeywords() for the build but it isn't working. Using Unity 2020.3.15f2 and HDRP 10.5.1 with the Lit Shader
     
  19. adrien-de-tocqueville

    adrien-de-tocqueville

    Unity Technologies

    Joined:
    Mar 16, 2020
    Posts:
    270
    Hello, you can find documentation on material setup here.
    Essentially HDRP materials need to have some keywords and properties set up before they can be rendered correctly.
    In the editor this step is done automatically when showing the inspector. For materials created from scripts it is not automatic.

    Starting from HDRP 13 you have access to the following API: HDMaterial.ValidateMaterial(material);
    that does the setup
    For older versions, you can use the following one, but it's only available in the editor (not at runtime): HDShaderUtils.ResetMaterialKeywords(material)
     
    gregStagwell likes this.
  20. GXMark

    GXMark

    Joined:
    Oct 13, 2012
    Posts:
    515
    If you want proper material setup at editor and runtime in standard, URP and HDRP then the way i do it is simply to create a resources materials folder in your project view and simply reinstance the different flavours you desire.

    Material mat = new Material(Resources.Load<Material>(path);

    Note that any materials you define in the resources folder will automatically get prepared at runtime for you during a build.
     
  21. superaldo666

    superaldo666

    Joined:
    Aug 30, 2013
    Posts:
    17
    Hi @adrien-de-tocqueville I have a problem with HDMaterial.ValidateMaterial() is only work in the editor and runtime, but no work when I build my app, could you please help me with that
     
  22. adrien-de-tocqueville

    adrien-de-tocqueville

    Unity Technologies

    Joined:
    Mar 16, 2020
    Posts:
    270
    Hello, i don't have enough information to help you here, but if it works in the editor and not in a standalone build then maybe it's a bug. If you can make a small repro project and report it we could have a look
    https://unity3d.com/unity/qa/bug-reporting
     
  23. benthroop

    benthroop

    Joined:
    Jan 5, 2007
    Posts:
    263
    So, is there a runtime solution for HDRP prior to v13? This is the kind of thing that should really be backported.

    Did this ever get bugged?