Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

How can I fade in/out a canvas group alpha color with duration time ?

Discussion in 'Scripting' started by SharonL75, Sep 14, 2020.

  1. SharonL75

    SharonL75

    Joined:
    Aug 13, 2020
    Posts:
    91
    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class FadeInOutSaveGameText : MonoBehaviour
    7. {
    8.     public Animator animator;
    9.  
    10.     // Start is called before the first frame update
    11.     void Start()
    12.     {
    13.        
    14.     }
    15.  
    16.     public void FadeOut()
    17.     {
    18.         animator.SetTrigger("FadeOut");
    19.     }
    20.  
    21.     public void FadeIn()
    22.     {
    23.         animator.SetTrigger("FadeIn");
    24.     }
    25.  
    26.     // Update is called once per frame
    27.     void Update()
    28.     {
    29.         if (Input.GetKeyDown(KeyCode.I))
    30.         {
    31.             FadeOut();
    32.         }
    33.  
    34.         if (Input.GetKeyDown(KeyCode.O))
    35.         {
    36.             FadeIn();
    37.         }
    38.     }
    39.  
    40.     public void FadeOutMessage(string message)
    41.     {
    42.         if(message == "FadeInEnded")
    43.         {
    44.             //FadeOut();
    45.         }
    46.     }
    47.  
    48.     public void FadeInMessage(string message)
    49.     {
    50.         if(message == "FadeOutEnded")
    51.         {
    52.             //FadeIn();
    53.         }
    54.     }
    55.  
    56.     public IEnumerator canvasAlphaOverTime(Canvas canvas, float duration)
    57.     {
    58.         float counter = 0;
    59.         var alphaColor = canvas.GetComponent<CanvasGroup>().alpha;
    60.  
    61.         while (counter < duration)
    62.         {
    63.             counter += Time.deltaTime;
    64.             alphaColor = Vector3.Lerp(/* FadeOut,  FadeIn*/, counter / duration);
    65.  
    66.             yield return null;
    67.         }
    68.     }
    69. }
    70.  
    In the canvasAlphaOverTime I want to change the alphaColor from 0 to 1 then back to 0 and then to 1 again make ping pong between 0 and 1 slowly smooth with speed.

    The duration is how many time it will make the ping pong !

    For example if the duration is 5 seconds then make ping pong between 1 and 0 and 0 and 1 for 5 seconds.
    After 5 seconds stop the transition between 1 and 0.

    The idea is that I give it a duration and it will ping pong make transition between 1 and 0 nonstop and after 5 seconds the transition will stop.

    So I have a problem to complete and make the line :

    Code (csharp):
    1.  
    2. alphaColor = Vector3.Lerp(/* FadeOut,  FadeIn*/, counter / duration);
    3.  
    And how to use the duration as overall time.
     
  2. SharonL75

    SharonL75

    Joined:
    Aug 13, 2020
    Posts:
    91
    This is more or less what I wanted, It's working in general but there are things to fix/add/change :

    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class FadeInOutSaveGameText : MonoBehaviour
    7. {
    8.     public Animator animator;
    9.     public Canvas canvas;
    10.     public float fadingSpeed;
    11.  
    12.     private bool stopFading = false;
    13.  
    14.     // Start is called before the first frame update
    15.     void Start()
    16.     {
    17.         StartCoroutine(OverAllTime(5f));
    18.     }
    19.  
    20.     IEnumerator CanvasAlphaChangeOverTime(Canvas canvas, float duration)
    21.     {
    22.         var alphaColor = canvas.GetComponent<CanvasGroup>().alpha;
    23.  
    24.         while (true)
    25.         {
    26.             alphaColor = (Mathf.Sin(Time.time * duration) + 1.0f) / 2.0f;
    27.             canvas.GetComponent<CanvasGroup>().alpha = alphaColor;
    28.  
    29.             if(stopFading == true)
    30.             {
    31.                 break;
    32.             }
    33.  
    34.             yield return null;
    35.         }
    36.     }
    37.  
    38.     IEnumerator OverAllTime(float time)
    39.     {
    40.         StartCoroutine(CanvasAlphaChangeOverTime(canvas, fadingSpeed));
    41.  
    42.         yield return new WaitForSeconds(time);
    43.  
    44.         stopFading = true;
    45.         StopCoroutine("CanvasAlphaChangeOverTime");
    46.     }
    47. }
    48.  
    Things to fix/change :

    * Does the line StopCoroutine really work ? If I'm not using the helper flag and make break; inside the loop then the fading weill never stop.

    * Should I use a helper flag and break; only or also StopCoroutine ?

    * When the CanvasAlphaChangeOverTime Coroutine stop then the fading also stop at the same point it is. but I want it to finish fading first depending on the fading direction. If it was changing to the 0 then first finish fading to 0 then stop the Coroutine and same if it was more then 0.5 changing to the 1 then first finish changing to 1 then stop the Coroutine.


    Things to add :

    * An option to change the fadingSpeed in real time while the fading is working ? How to do it ?
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,357
    I never use coroutines for fade in /out. Too big a chance of tangling yourself, having to rely on Stop Coroutine, getting two going at once, etc. Edge case nightmare.

    Instead, keep two variables:

    - current fade alpha
    - desired fade alpha

    Every update, if they are different, move the current towards the desired, usually with a small amount multiplied by Time.deltaTime.

    Use the current to set the fade out graphics, whatever those are.

    NOW... when you want to fade out, set the desired fade alpha to 1, when it's time to fade in, set it to 0.

    No way no matter how many different places all over your code say fade/unfade, whatever, as long as the last one is what you want, then the fading just happens. No coroutines, no statefullness, no edge cases, etc.
     
    D12294, Munchy2007 and SharonL75 like this.
  4. SharonL75

    SharonL75

    Joined:
    Aug 13, 2020
    Posts:
    91

    I tried this but the problem is that the transition from 0 to 1 or 1 to 0 is not smooth.
    It's just changing to 0 for example then jump to 1 and again change to 0 slowly but it's jumping to the other value it's not making smooth transition between the two values.

    What's wrong with this ? If the start alpha is 0 then it's moving slowly to 1 but then from 1 it's jumping nack to 0 and not moving slowly from 1 to 0 same if the start alpha is 1.

    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class FadeInOutSaveGameText : MonoBehaviour
    7. {
    8.     public Canvas canvas;
    9.     public float fadeDuration = 5;
    10.  
    11.     private float maxAlpha = 1;
    12.     private float lerpParam;
    13.     private float startAlpha;
    14.     private float canvasGroupAlpha;
    15.  
    16.     void Start()
    17.     {
    18.         canvasGroupAlpha = canvas.GetComponent<CanvasGroup>().alpha;
    19.         startAlpha = canvas.GetComponent<CanvasGroup>().alpha;
    20.     }
    21.  
    22.     void Update()
    23.     {
    24.         lerpParam += Time.deltaTime;
    25.  
    26.         canvasGroupAlpha = Mathf.Lerp(startAlpha, maxAlpha, lerpParam / fadeDuration);
    27.         canvas.GetComponent<CanvasGroup>().alpha = canvasGroupAlpha;
    28.         if (canvasGroupAlpha >= 1)
    29.         {
    30.             FadeTo(0);
    31.         }
    32.  
    33.         if (canvasGroupAlpha <= 0)
    34.         {
    35.             FadeTo(1);
    36.         }
    37.     }
    38.  
    39.     public void FadeTo(float alpha)
    40.     {
    41.         maxAlpha = alpha;
    42.         lerpParam = 0;
    43.     }
    44. }
    45.  
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,357
    Don't use Mathf.Lerp(). Use Mathf.MoveTowards().

    And definitely DO NOT USE COROUTINES (see my post above).

    make some member variables:

    Code (csharp):
    1. private float desiredAlpha;
    2. private float currentAlpha;
    The work:

    Code (csharp):
    1. void Update()
    2. {
    3.   currentAlpha = Mathf.MoveTowards( currentAlpha, desiredAlpha, 2.0f * Time.deltaTime);
    4. }
    Now, wherever you need to set fadedness of any object, use
    currentAlpha
    .

    Code (csharp):
    1. colorProperty.a = currentAlpha;
    When you want to change fadedness, only set
    desiredAlpha
    equal to 0 or 1.

    Code (csharp):
    1. desiredAlpha = 1.0f;
    That's it, you're done. It's actually that simple.
     
    Last edited: Nov 21, 2022
  6. Zer0Cool

    Zer0Cool

    Joined:
    Oct 24, 2014
    Posts:
    203
    Here some code that work with coroutines:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. /// <summary>
    6. /// Helper class to fade a canvas group for forum.unity.com by Zer0Cool
    7. /// - assign this script for instance to the gameobject that holds the canvas
    8. /// - assign canvas object to this script (if not set it uses the canvas on the same gameobject)
    9. /// - attach a canvas group to the gameobject that holds the canvas in your scene
    10. /// - set the animation curve to what you want (if not set it will use a default curve)
    11. /// - set a fading speed
    12. /// - choose which coroutine to execute (line 33)
    13. /// </summary>
    14.  
    15. public class FadeEffect : MonoBehaviour
    16. {
    17.     public Canvas canvas;
    18.     public AnimationCurve animationCurve;
    19.     public float fadingSpeed = 5f;
    20.  
    21.     public enum Direction { FadeIn, FadeOut};
    22.  
    23.     void Start()
    24.     {
    25.         if (canvas == null) canvas = GetComponent<Canvas>();
    26.         CanvasGroup canvasGroup = canvas.GetComponent<CanvasGroup>();
    27.         if (canvasGroup == null) Debug.LogError("Please assign a canvas group to the canvas!");
    28.  
    29.         if (animationCurve.length == 0)
    30.         {
    31.             Debug.Log("Animation curve not assigned: Create a default animation curve");
    32.             animationCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
    33.         }
    34.  
    35.         StartCoroutine(FadeCanvas(canvasGroup, Direction.FadeIn, fadingSpeed));
    36.         //StartCoroutine(FadeCanvas(canvasGroup, Direction.FadeOut, fadingSpeed));
    37.     }
    38.  
    39.     public IEnumerator FadeCanvas(CanvasGroup canvasGroup, Direction direction, float duration)
    40.     {
    41.         // keep track of when the fading started, when it should finish, and how long it has been running
    42.         var startTime = Time.time;
    43.         var endTime = Time.time + duration;
    44.         var elapsedTime = 0f;
    45.  
    46.         // set the canvas to the start alpha – this ensures that the canvas is ‘reset’ if you fade it multiple times
    47.         if (direction == Direction.FadeIn) canvasGroup.alpha = animationCurve.Evaluate(0f);
    48.         else canvasGroup.alpha = animationCurve.Evaluate(1f);
    49.  
    50.         // loop repeatedly until the previously calculated end time
    51.         while (Time.time <= endTime)
    52.         {
    53.             elapsedTime = Time.time - startTime; // update the elapsed time
    54.             var percentage = 1 / (duration / elapsedTime); // calculate how far along the timeline we are
    55.             if ((direction == Direction.FadeOut)) // if we are fading out
    56.             {
    57.                 canvasGroup.alpha = animationCurve.Evaluate(1f - percentage);
    58.             }
    59.             else // if we are fading in/up
    60.             {
    61.                 canvasGroup.alpha = animationCurve.Evaluate(percentage);
    62.             }
    63.  
    64.             yield return new WaitForEndOfFrame(); // wait for the next frame before continuing the loop
    65.         }
    66.  
    67.         // force the alpha to the end alpha before finishing – this is here to mitigate any rounding errors, e.g. leaving the alpha at 0.01 instead of 0
    68.         if (direction == Direction.FadeIn) canvasGroup.alpha = animationCurve.Evaluate(1f);
    69.         else canvasGroup.alpha = animationCurve.Evaluate(0f);
    70.     }
    71. }
    72.  
     
    Last edited: Sep 14, 2020