Search code examples
unity-game-enginetriggerscamerarenderer

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.


Solution

  • 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!