- Home /
Transitions between changing scenes
hey guys,
Is it possible to make transitions when changing scenes. So like it might fade out, or zoom out or whatever....
thanks :)
-Grady
i'm using this on my game, i would like to put you on the credits. please let me know carlosabreu1981@gmail.com
Answer by Bunny83 · May 22, 2011 at 03:12 AM
I've written a "small" script that allows you to load a level, but it fades the old level out and fades the new one in. The documentation states that the GL class is only available in Unity pro, but in my Unity version (3.0) it works fine in the free version ;)
// AutoFade.cs
using UnityEngine;
using System.Collections;
public class AutoFade : MonoBehaviour
{
private static AutoFade m_Instance = null;
private Material m_Material = null;
private string m_LevelName = "";
private int m_LevelIndex = 0;
private bool m_Fading = false;
private static AutoFade Instance
{
get
{
if (m_Instance == null)
{
m_Instance = (new GameObject("AutoFade")).AddComponent<AutoFade>();
}
return m_Instance;
}
}
public static bool Fading
{
get { return Instance.m_Fading; }
}
private void Awake()
{
DontDestroyOnLoad(this);
m_Instance = this;
m_Material = new Material("Shader \"Plane/No zTest\" { SubShader { Pass { Blend SrcAlpha OneMinusSrcAlpha ZWrite Off Cull Off Fog { Mode Off } BindChannels { Bind \"Color\",color } } } }");
}
private void DrawQuad(Color aColor,float aAlpha)
{
aColor.a = aAlpha;
m_Material.SetPass(0);
GL.PushMatrix();
GL.LoadOrtho();
GL.Begin(GL.QUADS);
GL.Color(aColor); // moved here, needs to be inside begin/end
GL.Vertex3(0, 0, -1);
GL.Vertex3(0, 1, -1);
GL.Vertex3(1, 1, -1);
GL.Vertex3(1, 0, -1);
GL.End();
GL.PopMatrix();
}
private IEnumerator Fade(float aFadeOutTime, float aFadeInTime, Color aColor)
{
float t = 0.0f;
while (t<1.0f)
{
yield return new WaitForEndOfFrame();
t = Mathf.Clamp01(t + Time.deltaTime / aFadeOutTime);
DrawQuad(aColor,t);
}
if (m_LevelName != "")
Application.LoadLevel(m_LevelName);
else
Application.LoadLevel(m_LevelIndex);
while (t>0.0f)
{
yield return new WaitForEndOfFrame();
t = Mathf.Clamp01(t - Time.deltaTime / aFadeInTime);
DrawQuad(aColor,t);
}
m_Fading = false;
}
private void StartFade(float aFadeOutTime, float aFadeInTime, Color aColor)
{
m_Fading = true;
StartCoroutine(Fade(aFadeOutTime, aFadeInTime, aColor));
}
public static void LoadLevel(string aLevelName,float aFadeOutTime, float aFadeInTime, Color aColor)
{
if (Fading) return;
Instance.m_LevelName = aLevelName;
Instance.StartFade(aFadeOutTime, aFadeInTime, aColor);
}
public static void LoadLevel(int aLevelIndex,float aFadeOutTime, float aFadeInTime, Color aColor)
{
if (Fading) return;
Instance.m_LevelName = "";
Instance.m_LevelIndex = aLevelIndex;
Instance.StartFade(aFadeOutTime, aFadeInTime, aColor);
}
}
You don't need to do anything with this script, just place it somewhere in your project. It creates automatically a GameObject when you use the LoadLevel function.
To load a new level just write in any of your scripts:
AutoFade.LoadLevel(1 ,3,1,Color.black);
// or
AutoFade.LoadLevel("MyLevelName" ,3,1,Color.black);
The 4 parameters are:
LevelName or LevelIndex
FadeOutTime - time in seconds until the level actually starts loading
FadeInTime - time in seconds until the fade-in process is completed.
FadeColor - this is the color the screen fades to.
Keep in mind that after calling AutoFade.LoadLevel
the game continues "FadeOutTime" seconds. You might want to block Input or something while the fade-process is active. Just check if AutoFade.Fading
is true.
Have fun ;)
edit here's my test project (webplayer required) where you can see the script in action. I've posted the link already in a comment below, but just in case you can't find it.
second edit
Since Time.deltaTime returns 0 when Time.timeScale is set to 0, it won't fade since the t value doesn't change. You can replace Time.deltaTime with Time.unscaledDeltaTime. That way it will work even when your game is paused. However this has one problem. Since unscaledDeltaTime is not modified / scaled / clamped, if the loading of the new level takes some time, unscaledDeltaTime might return huge values (well the time since the last frame which could even be seconds when using LoadLevel).
Time.deltaTime solves this problem by clamping the value to "Maximum Allowed Timestep". So if a frame takes longer than that it will be clamped to that value. You would have to do that manually. an alternative would be to just skip the first frame after the level load:
//[ ... ]
Application.LoadLevel(m_LevelIndex);
yield return null; // skip first frame in new level
while (t>0.0f)
//[ ... ]
However there might be other reasons why the unscaledDeltaTime going wrong so clamping it like Time.deltaTime is probably the best solution:
float unscaledClampedDT()
{
return Mathf.Clamp(Time.unscaledDeltaTime ,0.00001f, Time.maximumDeltaTime);
}
You might want to clamp it to a smaller value than maximumDeltaTime. maximumDeltaTime is usually 0.33333 (1/3) so it will skip into the fading by 1/3 of a second if the loading took more than that. It's probably the best to use both, the clampedDeltaTime and the yield to skip the first frame.
The changes would look like this:
//[...]
while (t<1.0f)
{
yield return new WaitForEndOfFrame();
t = Mathf.Clamp01(t + unscaledClampedDT() / aFadeOutTime);
DrawQuad(aColor,t);
}
if (m_LevelName != "")
Application.LoadLevel(m_LevelName);
else
Application.LoadLevel(m_LevelIndex);
yield return null; // skip first frame
while (t>0.0f)
{
yield return new WaitForEndOfFrame();
t = Mathf.Clamp01(t - unscaledClampedDT() / aFadeInTime);
DrawQuad(aColor,t);
}
//[...]
I may be speaking out of turn and @Bunny83 could whip out a JS version- but most people don't code two copies of everything they're doing to make sure they have it in both languages :)
converting C# to javascript is not that hard, it could be a good exercise to convert it yourself- give it a try! :D
errrr... i don't really know anything about c# though.... :/
It's pretty easy.. Just remember that c# is strictly typed, so functions require a return type. I remember seeing a thread on the unity forums that described all of the differences, but I don't have the link handy.
Well, since Unity has removed the ability to create a shader at runtime you have to use a shader that's in your project. However it is possible to still ship the shader within the script file and have it extracted automatically when used for the first time in the editor:
private void Awake()
{
DontDestroyOnLoad(this);
m_Instance = this;
m_$$anonymous$$aterial = Resources.Load<$$anonymous$$aterial>("Plane_No_zTest");
#if UNITY_EDITOR
if (m_$$anonymous$$aterial == null)
{
var resDir = new System.IO.DirectoryInfo(System.IO.Path.Combine(Application.dataPath, "Resources"));
if (!resDir.Exists)
resDir.Create();
Shader s = Shader.Find("Plane/No zTest");
if (s == null)
{
string shaderText = "Shader \"Plane/No zTest\" { SubShader { Pass { Blend SrcAlpha One$$anonymous$$inusSrcAlpha ZWrite Off Cull Off Fog { $$anonymous$$ode Off } BindChannels { Bind \"Color\",color } } } }";
string path = System.IO.Path.Combine(resDir.FullName, "Plane_No_zTest.shader");
Debug.Log("Shader missing, create asset: " + path);
System.IO.File.WriteAllText(path, shaderText);
UnityEditor.AssetDatabase.Refresh(UnityEditor.ImportAssetOptions.ForceSynchronousImport);
UnityEditor.AssetDatabase.LoadAssetAtPath<Shader>("Resources/Plane_No_zTest.shader");
s = Shader.Find("Plane/No zTest");
}
var mat = new $$anonymous$$aterial(s);
mat.name = "Plane_No_zTest";
UnityEditor.AssetDatabase.CreateAsset(mat, "Assets/Resources/Plane_No_zTest.mat");
m_$$anonymous$$aterial = mat;
}
#endif
}
The "UNITY_EDITOR" section within the Awake callback will only be included and executed when run inside the editor. All it does is saving the shader source code into a .shader file inside the Resources folder if it doesn't exist yet and also create a $$anonymous$$aterial asset. It also forces an asset reload so the shader becomes available. If the $$anonymous$$aterial exists already, nothing special happens. The normal runtime code just uses Resources.Load to get the material reference.
It's not very as nice as the old way, but there's no way around creating an actual shader asset in the project.
Any idea why the quads are not rendered at all (material loads fine) under Unity 5.2.1?
Answer by anwille_555 · Jul 30, 2017 at 03:35 PM
Any idea how to implement AutoFade to Scene Management in Unity?
Answer by trelobyte · Mar 12, 2014 at 06:25 PM
ok so the new version 4.3.4 seems that has killed the GL class on unity free...is there any alternatives to fading in and out of a scene ?
I just add it to my project and it's still works fine ( using unity n 4.3.4f1, no pro ).
Answer by Propagant · Sep 15, 2015 at 10:58 AM
I made easiest method of AutoFade in unity by Unity Game engine, UI elemets etc... You can free download it here... Fully explained and showed. Enjoy and thanks, if any opinions, just write. AutoFadeAlternative by matt