Fading in/out GameObject

14,056

Solution 1

Fading a Sprite is almost the-same as moving GameObject over time except that you modify its alpha instead of it's position.

The three most important stuff about fading an Object are Time.deltaTime, Mathf.Lerp/Color.Lerp and coroutine. You need to understand how these work together.

Start coroutine, use Time.deltaTime to increment a variable. That variable is used to use to determine how much that function has ran. In a for/while loop, use that variable that is incremented every-frame and the duration you want the fade to happen to generate the alpha with the help of the Mathf.Lerp function. Create new color with that alpha and and assign it to the Sprite.

This is done every frame until that variable that is incremented with Time.deltaTime reaches the duration you want to the fade to happen within.

Here is a simple SpriteRenderer fade function:

public SpriteRenderer spriteToFade;

IEnumerator fadeOut(SpriteRenderer MyRenderer, float duration)
{
    float counter = 0;
    //Get current color
    Color spriteColor = MyRenderer.material.color;

    while (counter < duration)
    {
        counter += Time.deltaTime;
        //Fade from 1 to 0
        float alpha = Mathf.Lerp(1, 0, counter / duration);
        Debug.Log(alpha);

        //Change alpha only
        MyRenderer.color = new Color(spriteColor.r, spriteColor.g, spriteColor.b, alpha);
        //Wait for a frame
        yield return null;
    }
}

If you want it to fade in, change Mathf.Lerp(1, 0, counter / duration); to Mathf.Lerp(0, 1, counter / duration); which will make the alpha go from 0 to 1 over-time instead of 1 to 0.


From the example above, writing a fade-out and fade-in functions only requires a way to tell the function to change the alpha from 1 to 0 or from 0 to 1. You can make the function use a boolean or enum variable to determine which type of fade to perform. Of-course, you can separate the fade-in/fade-out functions but it's good to have it in one function.

Here is the extended version of that function that supports fade-in and fade-out. It also supports almost all GameObjects like MeshRenderer(3D), SpriteRenderer(2D), Image, RawImage....You can extend it to support more components that's missing.

IEnumerator fadeInAndOut(GameObject objectToFade, bool fadeIn, float duration)
{
    float counter = 0f;

    //Set Values depending on if fadeIn or fadeOut
    float a, b;
    if (fadeIn)
    {
        a = 0;
        b = 1;
    }
    else
    {
        a = 1;
        b = 0;
    }

    int mode = 0;
    Color currentColor = Color.clear;

    SpriteRenderer tempSPRenderer = objectToFade.GetComponent<SpriteRenderer>();
    Image tempImage = objectToFade.GetComponent<Image>();
    RawImage tempRawImage = objectToFade.GetComponent<RawImage>();
    MeshRenderer tempRenderer = objectToFade.GetComponent<MeshRenderer>();
    Text tempText = objectToFade.GetComponent<Text>();

    //Check if this is a Sprite
    if (tempSPRenderer != null)
    {
        currentColor = tempSPRenderer.color;
        mode = 0;
    }
    //Check if Image
    else if (tempImage != null)
    {
        currentColor = tempImage.color;
        mode = 1;
    }
    //Check if RawImage
    else if (tempRawImage != null)
    {
        currentColor = tempRawImage.color;
        mode = 2;
    }
    //Check if Text 
    else if (tempText != null)
    {
        currentColor = tempText.color;
        mode = 3;
    }

    //Check if 3D Object
    else if (tempRenderer != null)
    {
        currentColor = tempRenderer.material.color;
        mode = 4;

        //ENABLE FADE Mode on the material if not done already
        tempRenderer.material.SetFloat("_Mode", 2);
        tempRenderer.material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
        tempRenderer.material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
        tempRenderer.material.SetInt("_ZWrite", 0);
        tempRenderer.material.DisableKeyword("_ALPHATEST_ON");
        tempRenderer.material.EnableKeyword("_ALPHABLEND_ON");
        tempRenderer.material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
        tempRenderer.material.renderQueue = 3000;
    }
    else
    {
        yield break;
    }

    while (counter < duration)
    {
        counter += Time.deltaTime;
        float alpha = Mathf.Lerp(a, b, counter / duration);

        switch (mode)
        {
            case 0:
                tempSPRenderer.color = new Color(currentColor.r, currentColor.g, currentColor.b, alpha);
                break;
            case 1:
                tempImage.color = new Color(currentColor.r, currentColor.g, currentColor.b, alpha);
                break;
            case 2:
                tempRawImage.color = new Color(currentColor.r, currentColor.g, currentColor.b, alpha);
                break;
            case 3:
                tempText.color = new Color(currentColor.r, currentColor.g, currentColor.b, alpha);
                break;
            case 4:
                tempRenderer.material.color = new Color(currentColor.r, currentColor.g, currentColor.b, alpha);
                break;
        }
        yield return null;
    }
}

Usage:

GameObject to fade:

public GameObject SpriteRend;

Fade-out in 3 seconds

StartCoroutine(fadeInAndOut(SpriteRend, false, 3f));

Fade-in in 3 seconds

StartCoroutine(fadeInAndOut(SpriteRend, true, 3f));

Solution 2

The way I have accomplished this has been change the alpha on the sprite color.

Color(R,G,B,A). A is the alpha.

  • SpriteRenderer.color = new Color(1f,1f,1f,1f) is opaque.
  • SpriteRenderer.color = new Color(1f,1f,1f,.5f) is about 50% transparent.
  • SpriteRenderer.color = new Color(1f,1f,1f,0f) is about 100% transparent, sprite cannot be seen.
Share:
14,056
goodwiag
Author by

goodwiag

Updated on June 21, 2022

Comments

  • goodwiag
    goodwiag almost 2 years

    I'm fairly new to coding, I'm still trying to develop that logic of thinking to help me create the solutions I'm wanting for games. Currently, I'm in Unity trying to create a 2D GameObject that's a wall hiding a secret door. I want that GameObject to fade out (about 90%) when the player GameObject triggers it, revealing the space behind and the hidden door.

    So far, I've managed to figure out how to render the "secret wall" GO inactive on the trigger, so it disappears, but this doesn't produce the visual that I'm going for. As I said, I'm still working on developing that coder's way of thinking, so while I've done a lot of research to solve this problem, many of the results I don't readily understand.

    Here's my code:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class SecretDoor1 : MonoBehaviour {
    
        void OnTriggerEnter2D (Collider2D SecretDoorTrig) {
             if (SecretDoorTrig.gameObject.tag == "Player") {
                 GetComponent<SpriteRenderer> ().enabled = false;
             }
             else {
                 GetComponent<SpriteRenderer> ().enabled = true;
             }
        }
    
        void OnTriggerExit2D (Collider2D SecretDoorTrig) {
    
             if (SecretDoorTrig.gameObject.tag == "Player") {
    
                 GetComponent<SpriteRenderer> ().enabled = true;
             }
             else {
                 GetComponent<SpriteRenderer> ().enabled = false;
             }
        }
    }
    
  • Draco18s no longer trusts SE
    Draco18s no longer trusts SE almost 7 years
    Its worth noting that the color objects can be cached to a field and reused.
  • goodwiag
    goodwiag almost 7 years
    @Laslos I hate to say it, but I do not know how to implement that code. Can you give me an example of how I would plug that in? I'll be applying these same effects to other GOs, so it would be useful to know.
  • Laslos
    Laslos almost 7 years
    @goodwiag to set the transparency of the door to 90%, set the color of the door GameObject: DoorGameObject.GetComponent<SpriteRenderer>().color = new Color(1f,1f,1f,.1f);