Fade in and fade out Script for Unity 3d

A Fader?:
Is your game looking for a bit of polish? Having a simple fade transition from scenes or transition from a point in a game can make all the difference.

The outcome:


The Method:
This uses a Coroutine to fade in/out over a specified time and using a specified amount of 'steps' for a smooth transition. This method takes a Unity UI image and adjusts the alpha until it is 0 or 100%.

    /// <summary>
    /// This is used when a Unity UI image is needed to fade
    /// </summary>
    /// <param name="image"></param>
    /// <param name="fadeIn"></param>
    /// <param name="fadeTimeSec"></param>
    /// <returns></returns>
    IEnumerator Fader(Image image, bool fadeIn, float fadeTimeSec)
    {
        // the alpha of the image cannot be set on its own so a new color needs to be created
        Color tempColor = image.color;
        // The amount when additioned or subtractioned that occur with that amount of steps wanted. (1.00f is the alpha at max)
        float fadeBreakDown = 1.00f / (float)fadeSteps;
        float waitTime = fadeTimeSec * fadeBreakDown;
        // Trying to get slightly more accurate interval times
        waitTime = waitTime - (waitTime/fadeSteps);
        if (fadeIn)
        {
            while (image.color.a <= 1)
            {
                yield return new WaitForSeconds(waitTime);
                tempColor.a += fadeBreakDown;
                image.color = tempColor;  
            }
        }
        else
        {
            while (image.color.a > 0)
            {
                yield return new WaitForSeconds(waitTime);
                tempColor.a -= fadeBreakDown;
                image.color = tempColor;
            }
        }        // set inactive // this will need to be adjusted depending on your use (such as: if alpha == 0 then setactive(false))
        //image.gameObject.SetActive(false);
        StopCoroutine(Fader(image, true, 0.0f));
    }

Where to go from here:
This can be used when transitioning from one UI menu to another or from menu to level or on level load. This code can be altered easily to fade a SpriteRenderer or a Material. The full script has a bonus method for use with a SpriteRenderer. I plan on using the core method to create a fade script for blood/water/mud on the camera screen. This use case is set to full opacity or none but can easily be altered as well to transition to/from a pause screen.

Why a Coroutine?
Yes this code could be used in the Update method using Time.deltatime or in combination with the OnGUI method but with this use case several of these methods can be called and used on different gameobjects. One limitation is this method can be off by up to 600 milliseconds when using short transition times, this only seems to occur when running the method form the Start method.

Let me know what you think. What would you do differently?
I hope this was helpful!
-James

Full Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Diagnostics; // used for a stopwatch

public class FaderScript : MonoBehaviour
{
    public SpriteRenderer spriteRend;
    public Image uiImage;
    [Tooltip("This is the amount of seconds the fade will take")]
    public float fadeTime;
    [Tooltip("This is the amount of 'steps' the fade will have")]
    [Range(1, 100)]
    public int fadeSteps;
    [Tooltip("FadeIn = True. FadeOut = False.")]
    public bool fadeIn;
    // from my tests the timing seems to be off by half a sec.
    //Stopwatch sw = new Stopwatch();
    void Start ()
    {
        StartCoroutine(Fader(spriteRend, fadeIn, fadeTime));
        StartCoroutine(Fader(uiImage, fadeIn, fadeTime));
    }
    /// <summary>
    /// This is used when a Unity UI image is needed to fade
    /// </summary>
    /// <param name="image"></param>
    /// <param name="fadeIn"></param>
    /// <param name="fadeTimeSec"></param>
    /// <returns></returns>
    IEnumerator Fader(Image image, bool fadeIn, float fadeTimeSec)
    {
        //sw.Start();
        // the alpha of the image cannot be set on its own so a new color needs to be created
        Color tempColor = image.color;
        // The amount when additioned or subtractioned that occur with that amount of steps wanted. (1.00f is the alpha at max)
        float fadeBreakDown = 1.00f / (float)fadeSteps;
        float waitTime = fadeTimeSec * fadeBreakDown;
        // Trying to get slightly more accurate interval times
        waitTime = waitTime - (waitTime/fadeSteps);
        if (fadeIn)
        {
            while (image.color.a <= 1)
            {
                yield return new WaitForSeconds(waitTime);
                tempColor.a += fadeBreakDown;
                image.color = tempColor;
                //print(tempColor.a);
                
            }
        }
        else
        {
            while (image.color.a > 0)
            {
                yield return new WaitForSeconds(waitTime);
                tempColor.a -= fadeBreakDown;
                image.color = tempColor;
                //print(tempColor.a);
            }
        }
        // set inactive // this will need to be adjusted depending on your use (such as: if alpha == 0 then setactive(false))
        //image.gameObject.SetActive(false);
        //sw.Stop();
        //print("Time: " + sw.ElapsedMilliseconds + " ms");
        StopCoroutine(Fader(image, true, 0.0f));
    }
    /// <summary>
    /// This is used when a sprite is needed to fade
    /// </summary>
    /// <param name="spriteRen"></param>
    /// <param name="fadeIn"></param>
    /// <param name="fadeTimeSec"></param>
    /// <returns></returns>
    IEnumerator Fader(SpriteRenderer spriteRen, bool fadeIn, float fadeTimeSec)
    {
        // the alpha of the spriteRenderer cannot be set on its own so a new color needs to be created
        Color tempColor = spriteRen.color;
        // The amount when additioned or subtractioned that occur with that amount of steps wanted. (1.00f is the alpha at max)
        float fadeBreakDown = 1.00f / (float)fadeSteps;
        float waitTime = fadeTimeSec * fadeBreakDown;
        // Trying to get slightly more accurate interval times
        waitTime = waitTime - (waitTime / fadeSteps);
        if (fadeIn)
        {
            while (spriteRen.color.a <= 1)
            {
                yield return new WaitForSeconds(waitTime);
                tempColor.a += fadeBreakDown;
                spriteRen.color = tempColor;
                //print(tempColor.a);
            }  
        }
        else
        {
            while (spriteRen.color.a > 0)
            {
                yield return new WaitForSeconds(waitTime);
                tempColor.a -= fadeBreakDown;
                spriteRen.color = tempColor;
                //print(tempColor.a);
            }
        }
        // set inactive // this will need to be adjusted depending on your use (such as: if alpha == 0 then setactive(false))
        //spriteRen.gameObject.SetActive(false);
        StopCoroutine(Fader(spriteRen, true, 0.0f));
    }
}

Comments

Popular posts from this blog

How to create slowly revealed text in a Unity 3d game

How different data structures can be used in game coding: List, Queue, and Stack

Tips on Improving the performance (fps) for your Unity game. (General topics)