Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unity material.color.a code is not working

 void OnTriggerStay(Collider other)
{
    if (other.gameObject.CompareTag("tree"))
    {
        Color color = other.gameObject.GetComponent<Renderer>().material.color;
        color.a = 0.5f;
    }
}

If an object with a "tree" tag enters the camera's trigger, I want the opacity of that object to be 0.5. But didn't worked. How can i fix this? Thanks.

like image 785
erenjeager Avatar asked Sep 30 '26 12:09

erenjeager


2 Answers

While the other two answers are technically correct, you are most likely missing a very important step to allow for the changing of the alpha of a Material. I'll take a guess and assume you generated a new Material in the Editor by using the Asset Creation Menu. By default, the Material RenderMode is set to Opaque.

To allow for changes of the Material color's alpha, you will need to set the RenderMode either to Transparent or Fade. If you are working with a custom shader, you will need to alter the code to format to one of the mentioned RenderTypes. If you need help modifying your shader, that would best be answered in a new question.

For clarity, here is a gif of what the confusion might be:

Example

Edit: For completeness, here is a full script that will toggle the RenderMode of your material at runtime if you do not wish to change it at compile time.

using UnityEngine;

public static class MaterialUtils
{
    public enum BlendMode
    {
        Opaque,
        Cutout,
        Fade,
        Transparent
    }

    public static void SetupBlendMode(Material material, BlendMode blendMode)
    {
        switch (blendMode)
        {
            case BlendMode.Transparent:
                material.SetOverrideTag("RenderType", "Transparent");
                material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
                material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                material.SetInt("_ZWrite", 0);
                material.DisableKeyword("_ALPHATEST_ON");
                material.EnableKeyword("_ALPHABLEND_ON");
                material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
                material.SetFloat("_Mode", 3.0f);
                break;
            case BlendMode.Opaque:
                material.SetOverrideTag("RenderType", "");
                material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
                material.SetInt("_ZWrite", 1);
                material.DisableKeyword("_ALPHATEST_ON");
                material.DisableKeyword("_ALPHABLEND_ON");
                material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                material.renderQueue = -1;
                material.SetFloat("_Mode", 0.0f);
                break;
            default:
                Debug.LogWarning("Warning: BlendMode: " + blendMode + " is not yet implemented!");
                break;
        }
    }
}

[RequireComponent(typeof(MeshRenderer))]
public class TestScript : MonoBehaviour
{
    [SerializeField] private MeshRenderer mr = null;
    [SerializeField] private float alphaChange = 0.5f;
    private bool isOpaque = true;

    private void Awake()
    {
        if (mr == null)
            mr = GetComponent<MeshRenderer>();
    }

    private void OnMouseDown()
    {
        // store our color struct and change the alpha channel
        Color clr = mr.material.color;
        clr.a = alphaChange;

        // instance our material to alter the rendermode
        Material mat = mr.material;

        // update our render mode to transparent and our color to the new alpha
        MaterialUtils.SetupBlendMode(mat, isOpaque ? MaterialUtils.BlendMode.Transparent : MaterialUtils.BlendMode.Opaque);
        mat.color = clr;

        // apply our material change
        mr.material = mat;

        // toggle our bool
        isOpaque = !isOpaque;
    }
}

Your original question does not state whether or not you need to toggle the material back to opaque, but I included it. You can keep the RenderMode as Transparent and simply change the alpha back to 1.0f to make it fully opaque again. Again, here's a gif example of the above script in action:

Example 2

To show that the snippet is working, I place 2 spheres behind the cubes. The snippet is probably a bit overkill for what you need, but if someone else stumbles on the question and needs a more versatile answer here it is!

like image 144
TEEBQNE Avatar answered Oct 02 '26 14:10

TEEBQNE


Color is just a struct and basically just a container of values without further functionality. It is not linked to the Material it was taken from.

By assigning only

color.a = XY;

you do nothing yet.

You have to assign it back to the material!

void OnTriggerStay(Collider other)
{
    if (!other.CompareTag("tree")) return;

    var material = other.GetComponent<Renderer>().material;
    var color = material.color;
    color.a = 0.5f;
    
    material.color = color;       
}        
like image 45
derHugo Avatar answered Oct 02 '26 14:10

derHugo