I have been playing around with this script but I’m not having much luck trying to get it to do what I want which is to fade out a game object just before the scene changes. My guess is I am not using the mesh renderer right?
using UnityEngine;
using System.Collections;
public class ObjectFader : MonoBehaviour {
public MeshRenderer[] renderers;
void Start(){
renderers = GetComponent<MeshRenderer> ();
}
// Update is called once per frame
void Update () {
Color alphaFadedColor = Color.white;
// modify alpha
// create your own time based algorithm and start it when you want the fade to start
alphaFadedColor.a = Time.realtimeSinceStartup / 10f;
foreach (MeshRenderer renderer in renderers) {
renderer.color = alphaFadedColor;
}
}
}
I found this code on the code Wiki that sort of works only it does some very strange things.
It seems to create a duplicate material in the inspector.
It fades out the outer ring of my 3D logo and not the middle even though it is all one mesh object.
If I adjust the alpha of the game object material manually it fades out just fine??
This is the script I’m using:
using UnityEngine;
using System.Collections;
public class ObjectFader : MonoBehaviour {
// publically editable speed
public float fadeDelay = 0.0f;
public float fadeTime = 0.5f;
public bool fadeInOnStart = false;
public bool fadeOutOnStart = false;
private bool logInitialFadeSequence = false;
// store colours
private Color[] colors;
// allow automatic fading on the start of the scene
IEnumerator Start ()
{
//yield return null;
yield return new WaitForSeconds (fadeDelay);
if (fadeInOnStart)
{
logInitialFadeSequence = true;
FadeIn ();
}
if (fadeOutOnStart)
{
FadeOut (fadeTime);
}
}
// check the alpha value of most opaque object
float MaxAlpha()
{
float maxAlpha = 0.0f;
Renderer[] rendererObjects = GetComponentsInChildren<Renderer>();
foreach (Renderer item in rendererObjects)
{
maxAlpha = Mathf.Max (maxAlpha, item.material.color.a);
}
return maxAlpha;
}
// fade sequence
IEnumerator FadeSequence (float fadingOutTime)
{
// log fading direction, then precalculate fading speed as a multiplier
bool fadingOut = (fadingOutTime < 0.0f);
float fadingOutSpeed = 1.0f / fadingOutTime;
// grab all child objects
Renderer[] rendererObjects = GetComponentsInChildren<Renderer>();
if (colors == null)
{
//create a cache of colors if necessary
colors = new Color[rendererObjects.Length];
// store the original colours for all child objects
for (int i = 0; i < rendererObjects.Length; i++)
{
colors[i] = rendererObjects[i].material.color;
}
}
// make all objects visible
for (int i = 0; i < rendererObjects.Length; i++)
{
rendererObjects[i].enabled = true;
}
// get current max alpha
float alphaValue = MaxAlpha();
// This is a special case for objects that are set to fade in on start.
// it will treat them as alpha 0, despite them not being so.
if (logInitialFadeSequence && !fadingOut)
{
alphaValue = 0.0f;
logInitialFadeSequence = false;
}
// iterate to change alpha value
while ( (alphaValue >= 0.0f && fadingOut) || (alphaValue <= 1.0f && !fadingOut))
{
alphaValue += Time.deltaTime * fadingOutSpeed;
for (int i = 0; i < rendererObjects.Length; i++)
{
Color newColor = (colors != null ? colors[i] : rendererObjects[i].material.color);
newColor.a = Mathf.Min ( newColor.a, alphaValue );
newColor.a = Mathf.Clamp (newColor.a, 0.0f, 1.0f);
rendererObjects[i].material.SetColor("_Color", newColor) ;
}
yield return null;
}
// turn objects off after fading out
if (fadingOut)
{
for (int i = 0; i < rendererObjects.Length; i++)
{
rendererObjects[i].enabled = false;
}
}
Debug.Log ("fade sequence end : " + fadingOut);
}
void FadeIn ()
{
FadeIn (fadeTime);
}
void FadeOut ()
{
FadeOut (fadeTime);
}
void FadeIn (float newFadeTime)
{
StopAllCoroutines();
StartCoroutine("FadeSequence", newFadeTime);
}
void FadeOut (float newFadeTime)
{
StopAllCoroutines();
StartCoroutine("FadeSequence", -newFadeTime);
}
// These are for testing only.
// void Update()
// {
// if (Input.GetKeyDown (KeyCode.Alpha0) )
// {
// FadeIn();
// }
// if (Input.GetKeyDown (KeyCode.Alpha9) )
// {
// FadeOut();
// }
// }
}
using UnityEngine;
using System.Collections;
public class MeshFader : MonoBehaviour
{
public float ColorSpeed = 2;
public MeshRenderer[] renderers;//Objects to fade
public Material FadeMaterial;
void Awake()
{
foreach (MeshRenderer renderer in renderers)
{
//Save object's original material data
Texture texture = renderer.material.GetTexture("_MainTex");
Color color = renderer.material.color;
//Switch to fade material
renderer.material = FadeMaterial;
color.a = 1;
//Put original material data on the new material
renderer.material.SetTexture("_MainTex", texture);
renderer.material.SetColor("_Color", color);
}
}
void Update()
{
foreach (MeshRenderer renderer in renderers)
{
Color color = renderer.material.color;
color.a -= 0.1f * Time.deltaTime * ColorSpeed;
renderer.material.SetColor("_Color", color);
}
}
}
This can looks unnatural depending on which shaders you are using on your objects.
Are your camera or objects moving/animating while fading? If not, another possible solution is to take an Screenshot of the current game view and fade that image.
I tried doing a delay with an IEnumerator but I must be using it wrong as I get errors… I so hate code
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
[RequireComponent(typeof(MeshRenderer))]
public class ColorChange : MonoBehaviour {
[SerializeField]
float duration;
float t = 0f;
Color color1 = Color.red, color2 = new Color(1f, 1f, 1f, 0f);
MeshRenderer meshRenderer;
public Color color;
void Awake(){
meshRenderer = GetComponent<MeshRenderer>();
yield return new WaitForSeconds(0.5f); // wait time
StartCoroutine(Fade());
}
// void Update() {
IEnumerator Fade(){
color = Color.Lerp(color1, color2, t);
t += Time.deltaTime / duration;
foreach (Material material in meshRenderer.materials) {
material.color = color;
}
}
}
I tried your code out too Mich_9 but I had the same problem, the outer ring of my logo fades but not the centre.
Now if I use the code supplied by “The Little Guy” my whole game object fades, which is perfect, the only thing this code would need now is a delay time I can set in the inspector.
As if this could not get more annoying… Oh sure try me… I’ll bet it can because I just discovered that this does not seem to work in the stand alone player build.
My logo does not fade out, it just changes color from red to white, and does not carry the metallic look it had in the editor? wtf??
Your running a bit of a dangerous script. On every Update() you are executing FadeLogo() with a delay of 18.7f seconds.
On mobile and the webplayer, there is a bit of a frame rate cap that will cause Update() by default to run about 60 times per second up to about 200… and on stand alone builds, it could run upwards of 500. This is probably causing the timing to go out of wack - plus it now has several tens of thousands of coroutines sitting and waiting.
I’d still go down a different path, but this should work relatively well for what you are needing. This will execute one single coroutine.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
[RequireComponent(typeof(MeshRenderer))]
public class ColorChange : MonoBehaviour
{
void Start()
{
StartCoroutine(FadeLogo());
}
/// <summary>
/// Fades in our logo over time
/// </summary>
/// <returns></returns>
IEnumerator FadeLogo()
{
Color colorFrom = Color.red;
Color colorTo = new Color(1f, 1f, 1f, 0f);
MeshRenderer meshRenderer = GetComponent<MeshRenderer>();
float duration = 1; // How long to run for
float remainingTime = duration; // How long we've been running to-date
float updateSpeed = 0.033f; // In seconds, approximately 30 fps
float delay = 10f; // Delay before it starts fading, in seconds
yield return new WaitForSeconds(delay); // Add a 10 second delay
while (remainingTime > 0) // While time is left on the clock
{
var ratio = remainingTime / duration; // get a value from 0 to 1
Color newColor = Color.Lerp(colorFrom, colorTo, ratio); // Find the colour
foreach (var mat in meshRenderer.materials) // Assign the colour
mat.color = newColor;
remainingTime -= Time.deltaTime; // Reduce what we've used up
yield return new WaitForSeconds(updateSpeed); // Wait for a specific time. Less smooth, but better on battery and CPU
// yield return new WaitForFixedUpdate(); // Alternatively, you can remove updateSpeed and run this every frame for a smoother transition, but it'll use more battery and CPU
}
Destroy(this.gameObject); // Something like this can then just remove the entire splash screen
}
}
Also if you just want to see where the hiccups were in your original script, this should help:
using UnityEngine;
public class ObjectFader : MonoBehaviour
{
public float FadeDuration = 10f; // Now, if you assign this to a game object, you can specify a Fade Duration
private MeshRenderer[] _meshRenderers; // Privates can't be modified from outside this script
private float _currentDuration;
private Color alphaColor = new Color(1f,1f,1f,1f);
void Start()
{
_currentDuration = FadeDuration;
_meshRenderers = GetComponentsInChildren<MeshRenderer>(); // this will now collect all the mesh renderers on this object, and all children objects
}
// Update is called once per frame
void Update()
{
foreach (MeshRenderer meshRenderer in _meshRenderers) // Go through this object and all children objects mesh renderers
{
foreach (var material in meshRenderer.materials) // Get all their materials
{
var ratio = _currentDuration / FadeDuration;
var newColor = Color.Lerp(material.color, alphaColor, ratio); // Note because the colour was already lerped in the previous update frame, this won't fade linearly.
material.color = newColor;
}
}
_currentDuration -= Time.deltaTime; // remove the amount, in seconds, since we last executed
if (_currentDuration < 0) // Are we out of time?
{
// Destroy script here
Destroy(gameObject);
}
}
}
In the second case, you could then assign it to game object and apply the fade to it and all its children by using:
var fo = someObject.AddComponent<ObjectFader>();
fo.FadeDuration = 10f;
Final mention, if you continue to look at this, you might also want to look into something like LeanTween (free asset on the asset store). It will make this much easier. Then to fade an object you just need to use something like:
Yeah kind of, its just a spinning 3D logo that I figured a slow fade out before the scene changes would be nicer that the sort of abrupt stop it would do just a fraction of a second before the scene changes.
Mich_9,
Take a look at my video, here you can see that it plays nice, but when I publish it out to the stand alone player it looses it’s nice shine and does not play like this. In the stand alone player it just changes the color which appears flat red to white and then destroys the game object.
Maybe the shader is falling back to a lower quality in the standalone build, losing his transparency property. Take a look at Shader LOD.
Try changing the quality settings for the standalone build to a higher value.
Also I suggest using a video for the animation instead of real-time rendered objects.
Check the debug log. It’s probably missing the shader you used and defaulted to one that isn’t set to transparency. By default not all shaders are included in builds.
I’d still seriously recommend fixing the script though.