Editor Script: enabling _METALLICGLOSSMAP keyword results in Metallic being set to 1

Hi all,

I’m using an Editor script to automatically apply Smoothness and Metallic properties to Materials with certain names, whenever an FBX is updated.

I recently learned that even though I set the smoothness/metallic values via script, in order to see those Material changes reflected in the Scene after the FBX is imported, I had to use:

mat.EnableKeyword("_METALLICGLOSSMAP");

Enabling this, however results in something weird. The Materials that got the correct Smoothness, now visually have Metallic stuck at 1 (so, fully metallic) when looking at the scene.

It seems to be a refresh problem, because if I go select the Material in the inspector, the Material in the scene suddenly updates to the correct graphical representation and loses its metallic look, and the Metallic slider reveals the correct value. I can move it back to 1.0 and reproduce how the scene looked before, right after the script is run.

Here’s the code I’m using:

        Material mat = (Material)AssetDatabase.LoadAssetAtPath(materialFilePath, typeof(Material));

        mat.EnableKeyword("_NORMALMAP");
        mat.EnableKeyword("_METALLICGLOSSMAP");

        // set its smoothness channel to albedo
        mat.SetInt("_SmoothnessTextureChannel", 1);

        // set it to the given smoothness (glossiness) value
        mat.SetFloat("_GlossMapScale", smoothness);

Even if I add:

mat.SetFloat("_Metallic", 0);

… when the script runs, the Material still appears in the scene as if it has a Metallic value of 1. And again, clicking on the Material thumbnail to bring up the inspector fixes it until the next time the asset is updated, but I can’t be doing this for all my Materials, manually.

I’ve verified this behavior on 2019.1.6f1 and 2019.2.0b7.

Am I missing another Keyword? I’ve tried everything I see in the shader, to no avail. Other ideas?

Thanks in advance.

@bgolus I’ve seen you post some very useful information about this stuff in other threads I’ve found online. Wondering if you have any thoughts on the behavior I’m seeing?

I should also note I’m using the Standard shader, and although this issue happens with all Materials that get the “_METALLICGLOSSMAP” keyword enabled, it’s particularly obvious with Materials like glass, which are transparent before the script runs, then suddenly look totally opaque and reflective after the keyword is set, until I inspect the material, then it looks like transparent glass with smoothness applied (which is how I wish it would look right after the script runs).

This keyword is if you want to use a texture that has the metallic and gloss values. The default texture for this slot is solid white, so fully metallic. If you don’t want to use a texture to set the metallic, don’t use this keyword.

When the above keyword is set, this value gets ignored, since the metallic value is assumed to be from the texture.

This isn’t used by the shader at all. It’s only used by the Standard shader’s custom material inspector to set the _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A keyword, which says to use the albedo texture’s alpha for gloss instead of the metallic texture. Setting that value without “looking at the material” in the editor (which runs the custom inspector) does nothing. Do not set this if you don’t want to use the albedo texture’s alpha to be used as the smoothness / gloss.

This is used to multiply the metallic (or albedo) texture’s alpha for gloss.

If you want to set the gloss / smoothness with out a texture, don’t set any of the keywords, and use _Glossiness instead.

There are a lot of keywords and material settings that are needed for transparent materials. Look at the custom editor’s code, starting at line #335
https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/Inspector/StandardShaderGUI.cs

1 Like

Thank you! I didn’t see your message until just now, and I was going to post here how I ended up solving it. Reading your post now, this might be kind of a hack!

I figured out how to create a little 100x100 PNG image in my script, and for all Materials, I simply create a solid-color RGB 0,0,0 (black) texture to assign as the Metallic texture, because most Materials don’t have metallic requirements currently. For Materials that should get a Metallic efffect, I create a different solid color based on the desired Metallic value (from 0-1). 50% metallic gives me an RGB 0.5,0.5,0.5 solid-color texture in the Metallic map slot. It seems to have worked but I probably don’t need to do all this work per @bgolus recommendations.

I’ve found it to be a nice effect to make the glossiness use the albedo texture’s alpha for the gloss map (the _SmoothnessTextureChannel option above). A floor texture in this way makes the gloss respond to the albedo texture which is exactly what it should do, for my use case. If I’m using this effect, do I need to keep _METALLICGLOSSMAP enabled, since it’s using the texture’s albedo alpha as a map?

No, only the keyword I mentioned above (along with the material property so the custom inspector doesn’t turn it back off if you look at it).

Also:

GPUs can’t use PNG files directly, so they have to be converted into a GPU friendly image format. That 100x100 texture is going to get imported into Unity and converted into a format the GPU can use. Most likely a DXT1. However a 1x1 texture would work just as well for this case and use way less memory. Not that you need it.

1 Like