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. Dismiss Notice

Question Transparency material doesn't work

Discussion in 'Scripting' started by zorro68, Jul 23, 2023.

  1. zorro68

    zorro68

    Joined:
    Nov 11, 2021
    Posts:
    8
    I have programming this simple class for craete a plane:

    Code (CSharp):
    1. public class pplane : MonoBehaviour
    2. {
    3.     public string gname = string.Empty;
    4.     public Color gcolor = Color.white;
    5.     public Vector3 gdelta = Vector3.one;
    6.     public Vector3 gposition = Vector3.zero;
    7.  
    8.     public void CreatePlane() {
    9.         GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
    10.         plane.name = gname;
    11.         plane.transform.position = gposition;
    12.         plane.transform.localScale = new Vector3(gdelta.x, gdelta.y, gdelta.z);
    13.  
    14.         Renderer renderer = plane.GetComponent<Renderer>();
    15.         if (renderer != null && renderer.material != null){
    16.             if (gcolor.a < 1.0f) {
    17.                 Material nuevo = new Material(Shader.Find("Standard")); //Transparent/Diffuse
    18.                 nuevo.SetFloat("_Mode", 3);
    19.                 //nuevo.color = gcolor;
    20.                 renderer.material = nuevo;
    21.             }
    22.             renderer.material.color = gcolor;
    23.         }
    24.     }
    25.     public void CreatePlane(Vector3 delta, Vector3 position, Color color, float opacity=1.0f, string name=""){
    26.         gname= name;
    27.         gdelta = delta;
    28.         gposition = position;
    29.         gcolor = color;
    30.         gcolor.a = opacity;
    31.  
    32.         CreatePlane();
    33.     }
    34. }
    and I call this as:

    Code (CSharp):
    1. void Start()
    2. {
    3.  
    4. GameObject planeObject = new GameObject("PlaneObject");
    5.         if (planeObject != null){
    6.             pplane plano = planeObject.AddComponent<pplane>();
    7.             if (plano != null) {
    8.  
    9.                 plano.CreatePlane(new Vector3(1.0f, 1.0f, 1.0f), new Vector3(-0.5f, 0, -0.5f), Color.grey, 0.5f, "suelo");
    10.             } else {
    11.                 Debug.LogError("No se encontró el componente Plane en el GameObject actual.");
    12.             }
    13.         }
    14.  
    15. }
    But I obtain a plane in fuchsia color, and without transparency.
    I have modified this code many times (reading in forum) but or it is in fuchsia or without transparency.
    Can anybody help me.

    Thanks in advance.
     

    Attached Files:

  2. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,630
    There's nothing wrong with your code. Pure fuchsia/pink is Unity's way to tell you the shader used by your material is invalid (doesn't compile due to errors, not compatible with your render pipeline, or null).

    I'd double check whether Shader.Find("Standard") is returning a valid shader.
     
  3. zorro68

    zorro68

    Joined:
    Nov 11, 2021
    Posts:
    8
    To find out if "nuevo" variable is correct, I have changed this:

    Code (CSharp):
    1. Material nuevo = new Material(Shader.Find("Transparent/Diffuse")); //Standard
    2.                 if (nuevo != null) {
    3.                     nuevo.SetFloat("_Mode", 3);
    4.                     //nuevo.color = gcolor;
    5.                     renderer.material = nuevo;
    6.                 }
    The "nuevo" variable returns me: "Legacy Shaders/Transparent/Diffuse (UnityEngine.Material)" (not null) and I understand that the shader is valid,.... or not?

    Thanks
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,560
    Anytime you do Find() stuff of any kind you are deep in crazy Ninja coding territory.

    For one, Unity simply will not include any assets that it doesn't see you reference directly.

    For two, your spelling of the name must be contextually perfect and unambiguous.

    A far better strategy is to drag in a single example Material, set up precisely the way you want it, and then pass that to
    new Material()
    to make copies.

    This Unity Way(tm) approach has the important advantage that it never fails. :)

    More generally, for find and get-related issues:

    In general, DO NOT use Find-like or GetComponent/AddComponent-like methods unless there truly is no other way, eg, dynamic runtime discovery of arbitrary objects. These mechanisms are for extremely-advanced use ONLY.

    If something is built into your scene or prefab, make a script and drag the reference(s) in. That will let you experience the highest rate of The Unity Way(tm) success of accessing things in your game.
     
  5. zorro68

    zorro68

    Joined:
    Nov 11, 2021
    Posts:
    8
    Thank you, Kurt, but (although this may not be important) I want to clarify that this is not for a game but for an app. My preference is to program everything with code and avoid using the editor. This is the reason I am facing this problem.

    I would like to create the Material in a class or function and use it from another class without relying on the Inspector or editor. And that's why I am doing so, but I am having this problem. I have program another class with a cylinder and I have the same problem even without taking the material into account (for example with a 1.0f value for gcolor.a).

    Do you know how can I do this correctly?

    Thanks
     
  6. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    510
    Some ideas:

    CreatePrimitive can be a little buggy and will sometimes create objects with the pink material.

    When creating the final build Unity won't include materials or shaders that aren't being used. So you should always make a reference to them somewhere in your project.
     
  7. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,630
    Unity will only include in your build stuff that's directly or indirectly referenced by any of the scenes included in the build, it doesn't look trough your code to figure out if you're manually retrieving and using any given asset.

    If your shader is not used by any material referenced in your scene(s), it won't be included in the build and so will be pink in the build (but will work in the editor).

    In that case you either also create the shader in your script, you add a reference to your shader in your script (so that Unity knows it's being used), or add the script to "Always included shaders" in the editor graphics settings.

    Shader.Find() only looks trough existing shaders.

    Well, it depends on which render pipeline you're using. I guess this shader is designed for BIRP (Built-in render pipeline) but if you're using URP or HDRP it won't work there.
     
    Last edited: Jul 25, 2023
  8. zorro68

    zorro68

    Joined:
    Nov 11, 2021
    Posts:
    8
    Thanks for your answer.

    Arkano says that the shader must be created in a script and add a reference, but how, can you show me a example?.
    Or add the script to "Always included shaders" in the editor graphics setting. For this, I have include some shaders in the "Always included shaders", but it doesn't work too ???? (I show you my graphics configuration).

    Sorry for my english, and I am new in unity and some concepts are new for me and they are not so intuitive....
     

    Attached Files:

  9. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,630
    Your screenshot clearly shows you're using URP (the "Scriptable Render Pipeline Settings" field has a URP asset in it), but the shaders you're trying to load so far ("Standard" and "Legacy Shaders/Transparent/Diffuse" are both intended to be used with BIRP, that's why it doesn't work.

    Quoting my first post:
    Either use a URP-compatible shader, or switch to the built-in render pipeline. You can't use a shader written for pipeline A on pipeline B, it just doesn't work that way: shaders are tied to a specific pipeline.
     
    Last edited: Jul 25, 2023
  10. zorro68

    zorro68

    Joined:
    Nov 11, 2021
    Posts:
    8
    Thanks arkano. I have been reading about URP and now I am understanding something more about shaders, materials and this topics. I think that this could be easier for beginners, and if you need advanced materials, you have to use shaders and more. But this is my opinion.
    I have been "playing" with URP and I have to correct the problem with the pink color, but I could not make the material transparent.
    I have now written a script to create a material and assigned it to the plane object. But I still don't see the transparentcy in the material (see picture).
    This is my code for the plane object:
    Code (CSharp):
    1. public class pplane : MonoBehaviour
    2. {
    3.     public string gname = string.Empty;
    4.     public Color gcolor = Color.white;
    5.     public Vector3 gdelta = Vector3.one;
    6.     public Vector3 gposition = Vector3.zero;
    7.  
    8.     //pmaterial MiMaterial = null;
    9.  
    10.     public void CreatePlane() {
    11.         GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
    12.         plane.name = gname;
    13.         plane.transform.position = gposition;
    14.         plane.transform.localScale = new Vector3(gdelta.x, gdelta.y, gdelta.z);
    15.  
    16.         pmaterial materialCreator = new pmaterial();
    17.         Material atomoMaterial = materialCreator.CreateMaterial(gcolor, gcolor.a);
    18.         if (atomoMaterial != null) {
    19.             Renderer renderer = plane.GetComponent<Renderer>();
    20.             if (renderer != null) {
    21.                 renderer.material = atomoMaterial;
    22.             }
    23.         }
    24.     }
    25.     public void CreatePlane(Vector3 delta, Vector3 position, Color color, float opacity=1.0f, string name=""){
    26.         gname= name;
    27.         gdelta = delta;
    28.         gposition = position;
    29.         gcolor = color;
    30.         gcolor.a = opacity;
    31.  
    32.         CreatePlane();
    33.     }
    34. }
    35.  
    36. public class pmaterial {
    37.     Color gcolor = Color.white;
    38.  
    39.     public Material CreateMaterial(Color color, float opacity = 1.0f) {
    40.         gcolor = color;
    41.         gcolor.a = opacity;
    42.                
    43.         Material atomoMaterial = new Material(Shader.Find("Universal Render Pipeline/Simple Lit")); //Transparent/Diffuse //Standard
    44.  
    45.         atomoMaterial.SetFloat("_Mode", 3);
    46.         atomoMaterial.SetFloat("_Surface", 1); // 0: Opaque, 1: Transparent
    47.         atomoMaterial.SetFloat("_BlendMode", 2); // 0: Alpha, 1: Premultiply, 2: Additive, 3: Multiply
    48.  
    49.         atomoMaterial.color = gcolor;
    50.  
    51.         atomoMaterial.SetOverrideTag("RenderType", "Transparent");
    52.         atomoMaterial.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
    53.  
    54.         return atomoMaterial;
    55.     }
    56. }
    And I create a plane like this:
    Code (CSharp):
    1. GameObject planeObject = new GameObject("PlaneObject");
    2.         if (planeObject != null){
    3.             pplane plano = planeObject.AddComponent<pplane>();
    4.             if (plano != null) {
    5.                 plano.CreatePlane(new Vector3(1.0f, 1.0f, 1.0f), new Vector3(-0.5f, 0, -0.5f), Color.grey, opacity: 0.5f,  name: "suelo");
    6.             } else {
    7.                 Debug.LogError("No se encontró el componente Plane en el GameObject actual.");
    8.             }
    9.         }
    Can you help me again?

    Thanks
     

    Attached Files:

  11. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,630
    Setting the opacity of a material should be really easy, imho you’re just making things unnecessarily hard for yourself.

    Typically you wouldn’t load a shader using Shader.Find and then set up material properties manually in a script, this is extremely brittle as the shader itself might change in upcoming Unity versions (different keywords, properties, tags, blending options, etc) and your code will stop working. This also ties your code to a specific shader, making things harder to maintain later on.

    As stated before the way this is intended to be done is to just have a public reference to your material in the script, then set its color/alpha value at runtime. This way you don’t have to create new materials at runtime or deal with shader keywords, things will work regardless of the shader used (as long as it supports transparency), Unity will know you’re actually using the material's shader in your project so you don’t have to add it to “always included shaders” for it to be included in builds, and most importantly your code will be a lot more robust and easier to understand and work with.
     
    Last edited: Jul 26, 2023
  12. zorro68

    zorro68

    Joined:
    Nov 11, 2021
    Posts:
    8
    Thank you for your patience, arkano. Sorry but due to family circumstances I have not been able to answer before.
    Setting the opacity of a material should be really easy, imho you’re just making things unnecessarily hard for yourself.

    As I told you, I agree with you on this, and I think this should be much simpler, and if I have taken this way it was because the transparency was not working for me (pink color).
    Now I'm going to take up the problem in a simple way, but remember that I need everything to be done by code, without using the editor.
    This is my simple code to create a plane (transparent):
    Code (CSharp):
    1. public class pplane : MonoBehaviour {
    2.     public string gname = string.Empty;
    3.     public Color gcolor = Color.white;
    4.     public Vector3 gdelta = Vector3.one;
    5.     public Vector3 gposition = Vector3.zero;
    6.  
    7.     public void CreatePlane() {
    8.         GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
    9.         plane.name = gname;
    10.         plane.transform.position = gposition;
    11.         plane.transform.localScale = new Vector3(gdelta.x, gdelta.y, gdelta.z);
    12.  
    13.         Renderer renderer = plane.GetComponent<Renderer>();
    14.         if (renderer != null && renderer.material != null) {
    15.             renderer.material.color = gcolor;
    16.         }
    17.     }
    18.  
    19.     public void CreatePlane(Vector3 delta, Vector3 position, Color color, float opacity=1.0f, string name=""){
    20.         gname= name;
    21.         gdelta = delta;
    22.         gposition = position;
    23.         gcolor = color;
    24.         gcolor.a = opacity;
    25.  
    26.         CreatePlane();
    27.     }
    and call this class like this:
    Code (CSharp):
    1. GameObject planeObject = new GameObject("PlaneObject");
    2.         if (planeObject != null){
    3.             pplane plano = planeObject.AddComponent<pplane>();
    4.             if (plano != null) {
    5.                 plano.CreatePlane(new Vector3(1.0f, 1.0f, 1.0f), new Vector3(-0.5f, 0, -0.5f), Color.grey, opacity: 0.5f,  name: "suelo");
    6.             } else {
    7.                 Debug.LogError("No se encontró el componente Plane en el GameObject actual.");
    8.             }
    9.         }
    And doesn't work. The plane is not transparent (see picture). Why???

    Thanks....
     

    Attached Files:

  13. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,630
    This code doesn't do anything in regards to transparency, besides setting the material's color (which I assume has an alpha value < 1).

    Which material/shader is your plane using? If it's the URP Lit shader, you must change its surface type Opaque to Transparent, otherwise alpha values will be ignored (since the material is well, opaque :))
     
  14. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    I would personally make the plane a prefab, and have any colors/materials cached/saved in some way. And the plane prefab have a script that handles it's "changes", so all you'd have to do is say
    currentPlane.ChangeMaterial(brownColor);
    . Or something along those lines. :)