Instantiated Decal does not Render

I am encountering an issue when instantiating a prefab at runtime that includes a decal projector component. The decal material is programmatically created and assigned values. However, after instantiating the decal object, it doesn’t render the decal. Strangely, if I pause the Unity editor and make any adjustment to a property of the decal’s material, the decal suddenly starts rendering correctly. This issue has been consistent across various versions of Unity, specifically in the 2021.3.x series.

I’m curious to know if anyone else has faced a similar problem with this issue.

This is an issue usually seen because the material keywords are not set properly.
In later version, an API function is available to do this, ValidateMaterial : https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@17.0/api/UnityEngine.Rendering.HighDefinition.HDMaterial.ValidateMaterial.html

But not in 2021.3.x, where you will have to use Material.SetKeyword and find the proper keywords to have the material working. You can inspect the material with the “debug” inspector to see what keyword are enabled when it is working.

Are Keywords different from material properties? This is my current code for creating material and setting it

SprayMaterial = new Material(LiveSprayShader);
SprayMaterial.SetTexture("_BaseMap", wheels[Index].Spray.SpraySprite);

LiveSprayShader is a custom Decal shader made in shadergraph. Could you please point me in a certain direction to resolve this issue?

I think when you instantiate a material from a shader, you need to set the right shader keywords (i.e. different compiled variants of the shader).

But putting that aside for a second… how about instead of instantiating your material from a shader, you could instantiate your material from a material. So where you have LiveSprayShader right now, that would be a working material sitting in your assets. SprayMaterial = new Material(SourceMaterial) will then give you the instance where you can set the unique texture or whatever.

Also - do you even need unique material instances? If so, the method I always use is as above, spawning a material from a material.

I haven’t previously worked with shader keywords so the concept is quite new to me. I’m gonna look up docs for further information regarding keywords.

Instantiating a copy from existing material sounds like a good idea but according to first response I got, a material needs to be validated after making changes to its properties or keywords through code. The validation was introduced in HDRP 13.x+. Since Unity 2021.3.x is running on 12.x so current work around I got is using this method after setting properties:

HDShaderUtils.ResetMaterialKeywords(SprayMaterial);

This actually fixes the issue in the editor but I reckon its an editor method so when I try to make a build it gives me error that the type or namespace doesn’t exist.

And I need unique materials because there can be multiple sprays (decals) in the scene and if they share same material then they will have same material properties being set. That’s where I create a new material for each spray and then it gets destroyed after its timer.

If you have an already set and validated decal material (you’ve set everything good in the inspector already), when it will be instanced if will keep the keywords. Changing the texture to an other one, changing the color or some slider value will not affect the keywords and it should just work.
Keywords are used for “drastic” material changes, like the material type, or some costly settings (like using triplanar mapping instead of UVs).