HDRP - Make surface transparent in runtime

Hello all.

I am new in Unity, so, may be it is stupid question, but I cannot find solution.

We need to develop application which display dynamically generated transparent objects.

We use HDRP pipeline,

In empty scene I added empty game object and in Start() method of this object I added code:

foreach (var planeSurface in loadedData.PlaneSurfaces)
{
    var points = new Vector3[planeSurface.Points.Length];
    for (int i = 0; i < planeSurface.Points.Length; i++)
    {
        var pnt = planeSurface.Points[i];
        points[i] = new Vector3((float)pnt.X, (float)pnt.Z, (float)pnt.Y);
    }

    GameObject plane = new GameObject("Plane");
    MeshFilter meshFilter = (MeshFilter)plane.AddComponent(typeof(MeshFilter));
    meshFilter.mesh = CreateMesh(points, planeSurface.TrianglesVertexIndexes);
    MeshRenderer renderer = plane.AddComponent(typeof(MeshRenderer)) as MeshRenderer;
    renderer.material.shader = Shader.Find("HDRenderPipeline/Lit");

    // !!!!! Set Surface Type to Transparent as I understand
    renderer.material.SetFloat("_SurfaceType", 1.0f);
    // !!!!! Set Alpha chanel to 0.3
    renderer.material.SetColor("_BaseColor", new Color(1.0f, 0.0f, 0.0f, 0.3f));

    renderer.material.SetFloat("_Metallic", (float)planeSurface.Reflection / 100.0f);
    renderer.material.SetFloat("_Smoothness", (float)planeSurface.Reflection / 100.0f);
}

I set surface type to Transparent and Alpha chanel value to 0.3.
But surfaces are not transparent, see image:

When I manually change Alpha value in the Unity editor it become transparent.

It seems I need to update material or redraw objects after setting these values in the code.
What I missed?

Why I see correct values in the properties but they are not applied to the objects?
Why they are applied when I change it in editor?

May be there is another way to make surface transparent?

Thanks.

You can’t dynamically create a transparent material for optimisation reasons (toggling the surface type to transparent in the editor will trigger defines in the shader to change how it is compiled).
However, you could reference an already existing transparent material to you script, and use it as a base to clone it and change it’s properties do your needs.

6 Likes

OK, Now it become clear. Thank you for help, I will create transparent material.

I couldn’t do this on a shader made with shader graphs in LWRP.
I followed this is steps, but it does not work. The material at run time does not change visually:

Hi Remy, should the solution posted by juliodutracora work? https://answers.unity.com/questions/1608815/change-surface-type-with-lwrp.html

It seems like the proper thing to do is to have 2 materials, one opaque and one transparent, and switch materials on the mesh as needed.

yep ok I will do that. Thanks

Came across this with a similar issue after switching to HDRP. I have a character with several armor slots that sometimes get textured by the equipment and wanted to add a stealth effect that made you transparent. anyways after reading this i worked out the following if it helps anyone else:

//material with transparent surface type and .5 a, set in inspector
   public Material Transparent;

   private bool isInvis;
   //well trigger our "stealth" through a property on the player script
   public bool IsInvisible
   {
      get { return isInvis; }
      set
      {//we are invisible
         if (value)
         {                         //changableMaterials is set in start from the players render mesh materials and copied to DefaultMaterials (specifically for equipping gear)
            for(int mat = 0; mat < ChangableMaterials.Count; mat++)
            {
               //be sure to change the texture before copying
               Transparent.mainTexture = ChangableMaterials[mat].mainTexture;
               ChangableMaterials[mat].CopyPropertiesFromMaterial(Transparent);                      
            }
         }
         else
         {
            for (int mat = 0; mat < ChangableMaterials.Count; mat++)
            {
               var temptexture = ChangableMaterials[mat].mainTexture;
               ChangableMaterials[mat].CopyPropertiesFromMaterial(DefaultMaterials[mat]);
               ChangableMaterials[mat].mainTexture = temptexture;
            }
         }
         isInvis = value;
      }
   }

Anyone finding this in modern times, if you’re using ShaderGraph you MUST check “Allow Material Override” this will expose the built in properties and allow you to change them from code (like someMaterial.SetFloat("_AlphaClip", 1f)

If you want to see the properties available, you can just select the shadergraph asset, look in the inspector and scroll down the bottom of the “Properties” section.

3 Likes

It would work in editor , but there is no guaranty that it would work in a build:
When you enable/disable shader keywords and passes in the editor, the shader is recompiled on the fly, but a build requires to have all the shader variants pre-compiled.

1 Like

I did not understand what is not guaranteed to work in build. Changing 2 material that has different shader or changing 2 material that has same shader?

Maybe I’ve quoted the wrong post, but :

  • Swapping the material of a renderer to another one, referencing a material asset from a script, should always work, should they have the same shader or not.
  • Changing the material keywords and passes from a script is not guaranteed to work in a build.
1 Like

I’m not sure it was stated anywhere in this thread but also another advantage of cloning from an existing material when its stored in your resources folder is that unity knows about it and ensures that those material variants are preloaded in the game. This is an alternative to having to specify them under the graphics menu folder. If your also interested in persisting material state into property files and want to reduce on the potential hundreds of property values, then you can simply store the delta between the material variant and the changed properties of the cloned materials.

I had the same issue in Unity 2021.3 HDRP and I resolved it by writing

material.shader = material.shader;

It seems that this instruction forces the Unity to check if there where any changes on the material without having to go to the inspector and manually change any option so the material refreshes and the material does become transparent.

Below is my complete code for a small reference (alpha is set to 0.3f):

image

3 Likes