I have programming this simple class for craete a plane:
public class pplane : MonoBehaviour
{
public string gname = string.Empty;
public Color gcolor = Color.white;
public Vector3 gdelta = Vector3.one;
public Vector3 gposition = Vector3.zero;
public void CreatePlane() {
GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
plane.name = gname;
plane.transform.position = gposition;
plane.transform.localScale = new Vector3(gdelta.x, gdelta.y, gdelta.z);
Renderer renderer = plane.GetComponent<Renderer>();
if (renderer != null && renderer.material != null){
if (gcolor.a < 1.0f) {
Material nuevo = new Material(Shader.Find("Standard")); //Transparent/Diffuse
nuevo.SetFloat("_Mode", 3);
//nuevo.color = gcolor;
renderer.material = nuevo;
}
renderer.material.color = gcolor;
}
}
public void CreatePlane(Vector3 delta, Vector3 position, Color color, float opacity=1.0f, string name=""){
gname= name;
gdelta = delta;
gposition = position;
gcolor = color;
gcolor.a = opacity;
CreatePlane();
}
}
and I call this as:
void Start()
{
GameObject planeObject = new GameObject("PlaneObject");
if (planeObject != null){
pplane plano = planeObject.AddComponent<pplane>();
if (plano != null) {
plano.CreatePlane(new Vector3(1.0f, 1.0f, 1.0f), new Vector3(-0.5f, 0, -0.5f), Color.grey, 0.5f, "suelo");
} else {
Debug.LogError("No se encontró el componente Plane en el GameObject actual.");
}
}
}
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.
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.
To find out if “nuevo” variable is correct, I have changed this:
Material nuevo = new Material(Shader.Find("Transparent/Diffuse")); //Standard
if (nuevo != null) {
nuevo.SetFloat("_Mode", 3);
//nuevo.color = gcolor;
renderer.material = nuevo;
}
The “nuevo” variable returns me: “Legacy Shaders/Transparent/Diffuse (UnityEngine.Material)” (not null) and I understand that the shader is valid,… or not?
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™ 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™ success of accessing things in your game.
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).
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.
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.
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…
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.
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:
public class pplane : MonoBehaviour
{
public string gname = string.Empty;
public Color gcolor = Color.white;
public Vector3 gdelta = Vector3.one;
public Vector3 gposition = Vector3.zero;
//pmaterial MiMaterial = null;
public void CreatePlane() {
GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
plane.name = gname;
plane.transform.position = gposition;
plane.transform.localScale = new Vector3(gdelta.x, gdelta.y, gdelta.z);
pmaterial materialCreator = new pmaterial();
Material atomoMaterial = materialCreator.CreateMaterial(gcolor, gcolor.a);
if (atomoMaterial != null) {
Renderer renderer = plane.GetComponent<Renderer>();
if (renderer != null) {
renderer.material = atomoMaterial;
}
}
}
public void CreatePlane(Vector3 delta, Vector3 position, Color color, float opacity=1.0f, string name=""){
gname= name;
gdelta = delta;
gposition = position;
gcolor = color;
gcolor.a = opacity;
CreatePlane();
}
}
public class pmaterial {
Color gcolor = Color.white;
public Material CreateMaterial(Color color, float opacity = 1.0f) {
gcolor = color;
gcolor.a = opacity;
Material atomoMaterial = new Material(Shader.Find("Universal Render Pipeline/Simple Lit")); //Transparent/Diffuse //Standard
atomoMaterial.SetFloat("_Mode", 3);
atomoMaterial.SetFloat("_Surface", 1); // 0: Opaque, 1: Transparent
atomoMaterial.SetFloat("_BlendMode", 2); // 0: Alpha, 1: Premultiply, 2: Additive, 3: Multiply
atomoMaterial.color = gcolor;
atomoMaterial.SetOverrideTag("RenderType", "Transparent");
atomoMaterial.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
return atomoMaterial;
}
}
And I create a plane like this:
GameObject planeObject = new GameObject("PlaneObject");
if (planeObject != null){
pplane plano = planeObject.AddComponent<pplane>();
if (plano != null) {
plano.CreatePlane(new Vector3(1.0f, 1.0f, 1.0f), new Vector3(-0.5f, 0, -0.5f), Color.grey, opacity: 0.5f, name: "suelo");
} else {
Debug.LogError("No se encontró el componente Plane en el GameObject actual.");
}
}
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.
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):
public class pplane : MonoBehaviour {
public string gname = string.Empty;
public Color gcolor = Color.white;
public Vector3 gdelta = Vector3.one;
public Vector3 gposition = Vector3.zero;
public void CreatePlane() {
GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
plane.name = gname;
plane.transform.position = gposition;
plane.transform.localScale = new Vector3(gdelta.x, gdelta.y, gdelta.z);
Renderer renderer = plane.GetComponent<Renderer>();
if (renderer != null && renderer.material != null) {
renderer.material.color = gcolor;
}
}
public void CreatePlane(Vector3 delta, Vector3 position, Color color, float opacity=1.0f, string name=""){
gname= name;
gdelta = delta;
gposition = position;
gcolor = color;
gcolor.a = opacity;
CreatePlane();
}
and call this class like this:
GameObject planeObject = new GameObject("PlaneObject");
if (planeObject != null){
pplane plano = planeObject.AddComponent<pplane>();
if (plano != null) {
plano.CreatePlane(new Vector3(1.0f, 1.0f, 1.0f), new Vector3(-0.5f, 0, -0.5f), Color.grey, opacity: 0.5f, name: "suelo");
} else {
Debug.LogError("No se encontró el componente Plane en el GameObject actual.");
}
}
And doesn’t work. The plane is not transparent (see picture). Why???
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 :))
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.