Fading Scenes help!

Hey there! I tried to write a script that will make my scenes fade in and out each time i load a new one. Here is the first script that i assigned on an empty game object.

using UnityEngine;
using System.Collections;

public class Fading : MonoBehaviour {

   public Texture2D fadeOutTexture;  // the texture that will overlay the screen. This can be a black image or a loading graphic
   public float fadeSpeed = 0.8f;  // the fading speed

   private int drawnDepth = -1000;  // the texture's order in the draw hierarchy: a low number means it renders on top(last)
   private float alpha = 1.0f;  // the texture's alpha value between 0 and 1
   private int fadeDir = -1;  // the direction to fade: in = -1 or out = 1

   void OnGUI () {
     // fade out/in the alpha value using a direction, a speed and Time.deltatime to convert the operation to seconds
     alpha += fadeDir * fadeSpeed * Time.deltaTime;
     // force (clamp) the number between 0 and 1 because GUI.color uses alpha values between 0 and 1
     alpha = Mathf.Clamp01 (alpha);

     // set color of our GUI (in this case our texture). All color values remain the same & Alpha is set to the alpha variable
     GUI.color = new Color (GUI.color.r, GUI.color.g, GUI.color.b, alpha);  // set the Alpha value
     GUI.depth = drawnDepth;  // make the black texture render on top (drawn last)
     GUI.DrawTexture (new Rect (0, 0, Screen.width, Screen.height), fadeOutTexture);  // draw the texture to fit the entire screen area
   }

   // sets the fadeDir to the direction parameter making the scene fade in if -1 and out if 1
   public float StartFade (int direction) {
     fadeDir = direction;
     return (fadeSpeed);  // return the fadeSpeed variable so it's easy to calculate the Application.LoadLevl();
   }

   // OnLevelWasLoaded is called when a level is loaded. It takes loaded level index (int) as a parameter so you can limit the fade in to certain scenes
   void OnLevelWasLoaded () {
     // alpha = 1;  // use this if the alpha is not set to 1 by default
     StartFade (-1); // call the fade in function
   }
}

and then i have 2 scripts that will load a new scene when they are clicked and i added this code on them :

using UnityEngine;
using System.Collections;

public class OnClick : MonoBehaviour {

   void OnMouseDown()
   {
     Application.LoadLevel("Main Menu");
   }

   public void FadeFunction () {
     // fade out the game and load a new level
     float fadeTime = GameObject.Find ("SceneFader").GetComponent<Fading>.StartFade(1);
     yield return new WaitForSeconds (fadeTime);
     Application.LoadLevel (Application.loadedLevel + 1);
   }
}

and a similar one to the other object. However i get this error :
Assets/Scripts/OnClick.cs(11,21): error CS1624: The body of OnClick.FadeFunction()' cannot be an iterator block because void’ is not an iterator interface type.

Please help me thanks!

you are using a returntype void as a coroutine, make it IEnumerator instead of void and use StartCoroutine to call it.

Can you send me the code i should write for this to work because i’ve seen other posts telling me to do this but i cannot figure out the code!

if you want to use a yield, you need a iterator that you can yield, check the Yield keyword on MSDN
like the example in the docs. it calls the Coroutine in Start, so it calls upon the IEnumerator for one frame. But the IEnumerator will run up until the new return WaitForSeconds every frame, waitTime x framerate times.
So although it’s not being called upon it will still finish it’s iteration.

When and where do you call the public void FadeFunction()? If you have added it to a button OnClick event, you should make a void that calls the coroutine
as in:

public void StartFade()
{
    StartCoroutine(FadeFunction());
}
IEnumerator FadeFunction()
{
    ...code
}

I call the StartFade function at the first script in my post and use it on the second one. I apreciate your help but it is too hard for me to understand!

you could do something like this…

using UnityEngine;
using System.Collections;

public class FadeScreen : MonoBehaviour
{
    private int fadeValue;
    private float fade, fadeSpeed;
    private Texture2D texture;
    private bool isFading;

    int testInt = 1;

    void Start()
    {
        fade = -1;
        //create a texture
        texture = new Texture2D(1,1);
        texture.SetPixel(0,0,Color.black);
        texture.Apply();
    }
    //a function you can call when you need to fade,
    //if fadeTo is 1 you fade in if fadeTo is 0 you fade out
    public void StartFading(int fadeTo, float speed)
    {
        fadeValue = fadeTo;
        fadeSpeed = speed;
        //call the Coroutine
        StartCoroutine("Fade");
    }
    public IEnumerator Fade()
    {
        float lerp = 0;
        while(fade != fadeValue)
        {
            lerp += Time.deltaTime*fadeSpeed;
            Mathf.Clamp01(lerp);
            fade = Mathf.Lerp(fade, fadeValue, lerp);
            isFading = true;
           
            yield return null;
        }
        isFading = false;
    }
    void Update()
    {
        //just for testing
        if(Input.GetKeyDown(KeyCode.Space) && !isFading)
        {
            if(testInt == 1)
                testInt = 0;
            else
                testInt = 1;
            StartFading(testInt, 0.1f);
        }
    }
    void OnGUI()
    {
        GUI.color = new Color(0f, 0f, 0f, fade);
        GUI.depth = 1;
        GUI.DrawTexture (new Rect (0, 0, Screen.width, Screen.height), texture);
    }
}

I added it on an empty game object but it didn’t do anything!

as you can read in the script it fades when you press space.

done that!But nope!

ah k, the test int started in the wrong state and fade == fadeValue takes to long.
this will work better:

using UnityEngine;
using System.Collections;

public class FadeScreen : MonoBehaviour
{
    private int fadeValue;
    private float fade, fadeSpeed;
    private Texture2D texture;
    public bool isFading;

    public int testInt = 0;

    void Start()
    {
        fade = -1;
        //create a texture
        texture = new Texture2D(1,1);
        texture.SetPixel(0,0,Color.black);
        texture.Apply();
    }
    //a function you can call when you need to fade,
    //if fadeTo is 1 you fade in if fadeTo is 0 you fade out
    public void StartFading(int fadeTo, float speed)
    {
        fadeValue = fadeTo;
        fadeSpeed = speed;
        //call the Coroutine
        StartCoroutine("Fade");
    }
    public IEnumerator Fade()
    {
        float lerp = 0;
        while(Mathf.Abs(fadeValue - fade)>0.01f)
        {
            lerp += Time.deltaTime*fadeSpeed;
            Mathf.Clamp01(lerp);
            fade = Mathf.Lerp(fade, fadeValue, lerp);
            isFading = true;
           
            yield return null;
        }
        isFading = false;
    }
    void Update()
    {
        //just for testing
        if(Input.GetKeyDown(KeyCode.Space) && !isFading)
        {
            if(testInt == 1)
                testInt = 0;
            else
                testInt = 1;
            StartFading(testInt, 0.1f);
        }
    }
    void OnGUI()
    {
        GUI.color = new Color(0f, 0f, 0f, fade);
        GUI.depth = 1;
        GUI.DrawTexture (new Rect (0, 0, Screen.width, Screen.height), texture);
    }
}

The script works when i press space but i want it to fade in and out when the blue dot is clicked so that the scene loading waits for the script to fade in and out the scene!

well as i do in Update(), StartFading(int fadeTo, float speed) can be called when you need it with the values you want.
StartFading(0, 0.5f); will fade out and StartFading(1, 0.5f) will fade in.
all you need is a reference the FadeScreen script with GetComponent();

Hey i think i am getting somehwere! I added the script on my blue dot game object that changes levels when clicked and i did this here :

using UnityEngine;
using System.Collections;

public class OnClick2 : MonoBehaviour {

   private float function;

   void start() {
     function = GetComponent<FadeScreen> ();
   }
   
   void OnMouseDown()
   {
     Application.LoadLevel("Level 2");
     StartFading (0, 0.5f);
     StartFading (1, 0.5f);
   }
   
}

But i get this error :
Assets/Scripts/OnClick2.cs(9,17): error CS0029: Cannot implicitly convert type FadeScreen' to float’

What kind of variable do i need to set it equal to getcomponent?

instead of private float function, just put private FadeScreen fadeScreen;
and in void Start fadeScreen = GetComponent();

Another error it still shows the StartFading(0,0.5f) in red!

error CS0103: The name `StartFading’ does not exist in the current context

you have to call StarFading on the fadeScreen instance… fadeScreen.StartFading(0,0.5f);
since it’s a function in the class FadeScreen.

I called : fadescreen.StartFading(0,0.5f) and it is not red anymore but still getting this error :
NullReferenceException: Object reference not set to an instance of an object
OnClick2.OnMouseDown () (at Assets/Scripts/OnClick2.cs:15)
UnityEngine.SendMouseEvents:smile:oSendMouseEvents(Int32)

I don’t know what you are doing but this supposed the be very simple :slight_smile:
Let me lay it out in detail:
every time you make a script in Unity, you actually are making a class. classes can have lots of stuff, among them are variables and functions.
there is a difference between a class and an object (or instance) as there is a difference between a blue print and a building.
So we made the class FadeScreen with the function StartFading in it. Since FadeScreen is not static we need an instance of this class (we can not simply say “take elevator” to nothing, we can not say “take elevator” with only a blueprint, but we can say “take elevator” if we have a building). so we need to take the elevator(StartFading) in the building (fadeScreen). so we need a building (instance) of FadeScreen.
and so we get our instance with:
for example on a trigger at the end of your level…

FadeScreen fadeScreen;
bool reachedEnd;

void Start()
{
    //getting the instance
    fadeScreen = GetComponent<FadeScreen>();
}

void OnTriggerEnter(Collider c)
{
    //checking if we ended the level
    if(c.tag == "LevelEnd")
        reachedEnd = true;
}
void Update()
{
    //fading out
    if(reachedEnd)
        fadeScreen.StartFading(0, 0.5f);
}

Yeah i know what you mean it’s just that my game is probably not correctly built or something!
Is there any way i can give you my project files just to see what i am doing wrong? Because i want the screen to fade when i change a level but the only thing i can think of is a OnClick function however, it does not work with this function. Should i go for a trigger?

I can’t promise anything but i will take a look if you want.