1

I have a canvas for UI, with an image the same size of the canvas. The image has an rgba of 0,0,0,0 , making it invisible (because the a is 0). I want to have the image fade into black from a script. The script is called by the button in the menu when it is clicked. Here is the code I am using:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class NavigationC : MonoBehaviour {
    private bool Starting = false;
    public Image screen;
    float fadeTime = 3f;

    void StartGame()
    {
        Starting = true;
        StartCoroutine(wait());
        screen.CrossFadeAlpha(1f, fadeTime, true);

    }
}

Picture of the image in inspector: Picture of the image in inspector

By changing some values I can get it to work, but it is far from ideal and it should be solveable instead of using this workaround. Here is the video: https://www.youtube.com/watch?v=3M-S0EHwwNk

For some reason I can get it to work using either 255 or 255f. I don't want to use such a workaround but I left these in the video to show my desired outcome (which is the fade).

Picture of the button which calls the function: enter image description here

Programmer
  • 121,791
  • 22
  • 236
  • 328
RnRoger
  • 682
  • 1
  • 9
  • 33
  • When people ask you to update your question with code, you're supposed to _edit_ it, not ask a new question. Also, questions are meant to be self-contained. If the video contains important information, then that clearly is not the case. I recommend reading [ask]. – dandan78 Feb 19 '17 at 17:38
  • He asked me to create a new question. The video was also a request. The information is all in the question itself, it is just visualization. – RnRoger Feb 19 '17 at 17:53
  • I fully understand after the video. I will try to replicate that and let you know. – Programmer Feb 19 '17 at 17:59
  • Did you ever realize that the `StartGame` function is not even being called anywhere? Nothing is calling it..... – Programmer Feb 19 '17 at 18:02
  • It has to, because it does work with other values. But yeah, sorry, it is being called from the button in the UI, my mistake for not telling you. – RnRoger Feb 19 '17 at 18:03
  • That's fine. I am still correct. I think that you are calling the wrong function. You can't call `StartGame` like that from the Button since it is not a `public` variable. It must be `public void StartGame(){...}` before it can be called from the Button from the Editor. Please, verify this. – Programmer Feb 19 '17 at 18:08
  • Like you saw yourself, it does work when I just change the value to 255. It is not called in a script but by a component, I added a picture to the post. I had public at some point, otherwise I couldn't have added it, I guess I removed it in testing at some point. It still works, I can display a `Debug.Log` for example but I can't reselect it in the button, changed it to `public`. A small mistake, but not the one we're looking for. – RnRoger Feb 19 '17 at 18:56
  • That's the thing though. Mistakes like these can make the comment section long and it will make the problem look like something else. I suggest you set that back to a public function. If you want to use a private function for the `Button` then register it [code](http://stackoverflow.com/a/41392130/3785314) through code instead of the Editor. This will save you or anyone on your team time in the future. Check my answer. – Programmer Feb 19 '17 at 21:57

1 Answers1

4

I can confirm that this is with CrossFadeAlpha. The workaround is to get the current color, set the Color.a to 1 then set it back to 0 with CrossFadeAlpha(0f, 0f, true);. After that, you can then call your screen.CrossFadeAlpha(1, fadeTime, false); function.

You wont see the effect of setting Color.a to 1 because you are setting it back to 0 with screen.CrossFadeAlpha(0f, 0f, true); in the-same frame.

This is the proper workaround and should fix this problem:

Color fixedColor = screen.color;
fixedColor.a = 1;
screen.color = fixedColor;
screen.CrossFadeAlpha(0f, 0f, true);

screen.CrossFadeAlpha(1, fadeTime, false);

You can also make it an extension method so that it can be used from any where in your project and on any UI component:

public static class ExtensionMethod
{
    public static void CrossFadeAlphaFixed(this Graphic img, float alpha, float duration, bool ignoreTimeScale)
    {
        //Make the alpha 1
        Color fixedColor = img.color;
        fixedColor.a = 1;
        img.color = fixedColor;

        //Set the 0 to zero then duration to 0
        img.CrossFadeAlpha(0f, 0f, true);

        //Finally perform CrossFadeAlpha
        img.CrossFadeAlpha(alpha, duration, ignoreTimeScale);
    }
}

Usage :

private bool Starting = false;
public Image screen;
float fadeTime = 3f;

public void StartGame()
{
    Starting = true;
    StartCoroutine(wait());
    screen.CrossFadeAlphaFixed(1, fadeTime, false);
}

I noticed that you have StartCoroutine(wait()); in your code. It looks like you simply want to wait until the fading is done then do something(load new scene). I suggest you roll your own fade function that takes a callback function with Action.

 public void StartGame()
 {
     Starting = true;

     CrossFadeAlphaWithCallBack(screen, 1f, fadeTime, delegate
      {
          Debug.Log("Done Fading");
          SceneManager.LoadScene(1);
      });
 }

 void CrossFadeAlphaWithCallBack(Image img, float alpha, float duration, System.Action action)
 {
     StartCoroutine(CrossFadeAlphaCOR(img, alpha, duration, action));
 }

 IEnumerator CrossFadeAlphaCOR(Image img, float alpha, float duration, System.Action action)
 {
     Color currentColor = img.color;

     Color visibleColor = img.color;
     visibleColor.a = alpha;


     float counter = 0;

     while (counter < duration)
     {
         counter += Time.deltaTime;
         img.color = Color.Lerp(currentColor, visibleColor, counter / duration);
         yield return null;
     }

     //Done. Execute callback
     action.Invoke();
 }

Again, you can make it an extension method so that it can be used anywhere in your project.

public static class ExtensionMethod
{
    public static void CrossFadeAlphaWithCallBack(this Image img, float alpha, float duration, System.Action action)
    {
        MonoBehaviour mnbhvr = img.GetComponent<MonoBehaviour>();
        mnbhvr.StartCoroutine(CrossFadeAlphaCOR(img, alpha, duration, action));
    }

    public static IEnumerator CrossFadeAlphaCOR(Image img, float alpha, float duration, System.Action action)
    {
        Color currentColor = img.color;

        Color visibleColor = img.color;
        visibleColor.a = alpha;


        float counter = 0;

        while (counter < duration)
        {
            counter += Time.deltaTime;
            img.color = Color.Lerp(currentColor, visibleColor, counter / duration);
            yield return null;
        }

        //Done. Execute callback
        action.Invoke();
    }
}

Usage:

private bool Starting = false;
public Image screen;
float fadeTime = 3f;

public void StartGame()
{
    Starting = true;

    screen.CrossFadeAlphaWithCallBack(1f, fadeTime, delegate
    {
        Debug.Log("Done Fading");
        SceneManager.LoadScene(1);
    });
}
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • Even though this is still a workaround and not a fix for the unknown problem/bug, thanks for your help it works. – RnRoger Feb 20 '17 at 00:35
  • 1
    Yeah it's a bug. That's better than using 255 to solve it. Remember that I made functions to do this without Unity's fade function. You should use them, especially the one with the callback function until Unity fixes that. – Programmer Feb 20 '17 at 00:55
  • Yeah, I will. Thanks for your help and patience. – RnRoger Feb 20 '17 at 07:12