How to Fade a GameObject in Unity
Many of the fancier effects achievable in Unity have roots in fairly basic operations, and one of the most common is making a GameObject fade in and out of sight. There are a few ways to get this done; we will discuss three of them.
1. Change the GameObject's Alpha from the Inspector
Though this method won't help you during runtime, the easiest way to fade an object in and out is to do it via the Inspector. We'll start with 2D objects. Once you have created a new 2D sprite you can access its Sprite Renderer component, and from there the Color attribute, like so:
You can then move the slide on the 'A' attribute beneath the color wheel to make the GameObject fade in and out of view. This is useful for pre-setting GameObjects you know should be fully- or semi-transparent. For example, if you wanted a character to look like a ghost, you could set the Alpha slider to a value of 128 or so, allowing you to still see the GameObject while also viewing any background images through the GameObject.
3D objects are a little more complex in this regard, as you need to manipulate the object's Material rather than the object itself. First, create a new Material by right-clicking in the Project view and scrolling to Create > Material, as pictured below:
You can then assign the New Material (or whatever you call it) to your GameObject via the Mesh Renderer component, which should be included with any new 3D object upon creation. Double-clicking the Material name will then bring up the Material's attributes in the Inspector.
From here you can again access the Color attribute to assign the GameObject a colour - though at first you probably won't be able to make it fade out properly. To fade a 3D GameObject the assigned Material must have its Rendering Mode (top of the Inspector) set to either CutOut, Fade, Or Transparent, and in the case of Transparent you can't make the object disappear entirely. Set it to CutOut or Fade for now. This will allow you to set the GameObject's Alpha to any number you like.
As with the method for 2D objects, however, this has the limitation of not being available during runtime. To achieve a full fade-in, fade-out effect while your game is playing you will need to do some work in C# - and as far as 3D objects are concerned, you now have the Material needed to make it work.
2. Use an Update Boolean
The next method for fading out a GameObject involves some work with the Update function, two other independent functions, and two booleans (true/false). Create a new script for your GameObject titled whatever you like - in this case we'll call it 'FadeObject' - and attach it to the object. In your new script you'll want to create two new functions, and a pair of booleans to go along with them. We will use these booleans to trigger the Update sequence that will fade in and fade out the GameObject.
Once you have that framework in place you'll need to set the functions to trigger the booleans when they're called.
(Technically you could dispense with the functions in this example and just use the booleans, but it's useful to have them in case other systems in your game need to trigger the fading-in / fading-out effect.)
Pretty simple so far. Now we need to create the meat of the process in the Update function, which checks for changes every frame and creates the smooth fading effect you probably want. We'll start with fading the GameObject out first. To set this up we'll need a new public float, fadeSpeed, and two local variables: fadeAmount (a float) and objectColor (a Color). These will be used to keep track of the new color values and determine which value is needed next.
Part of what makes changing colors tricky in Unity is how the values are manipulated. You can't just change one part of a color, you need to reassign every value in the color, whether the values have changed or not. Consequently, you need to take the current color values of your GameObject (this.GetComponent<Renderer>().material.color), assign them to a variable (objectColor), and subtract from there. You probably want the transition to look smooth, however, so the math you perform needs to work alongside the flow of time in Unity, like so:
Time.deltaTime is a useful representation of how long Unity waits between frames before completing another step in the execution of your code. The higher you set the fadeAmount value in the Inspector (which we will do in a bit), the faster the object will fade out. Time.deltaTime is also used for moving objects in Unity, among plenty of other things, so if you're a newcomer to programming in C# you can expect to see it often.
Once you have the amount to fade by you then subtract from the Alpha of objectColor (objectColor.a) to get a new Alpha value to plug into objectColor. (Note that you could also simply perform this calculation in the middle of the next line, but it's cleaner to do so in its own line.) Note again that you must assign values to each of the other three color values, which, in this case, do not change.
By setting each color to 'objectColor.r', and so on, you are simply re-using the old values. Very handy. Plug in fadeAmount at the end and then apply objectColor to your GameObject's color and you'll have a GameObject that is a little more faded out than it was before. Since Update runs continuously, this process will loop until the object is completely gone. Unfortunately, it will also continue to loop and eat up unnecessary memory if you don't stop it, so you'll want to throw in the if(objectColor.a <=0) statement at the end to set fadeOut to false. This will check whether or not the Alpha value has hit zero, and once it has Update will stop, well, updating.
Piece of cake, right? Right. Now we just need to test it. Put a little if(Input) statement in your Update function like so:
This will allow you to trigger the FadeOutObject() function whenever you press the A key on your keyboard. That done, go back into the Inspector, set your GameObject's fadeSpeed - 5 is a reasonable amount - and test your game via the Play button. Assuming you've done everything correctly, your GameObject will swiftly fade from view.
(Did it not work? Make sure your GameObject has a Renderer with a Material that can fade. The steps for doing so are listed above.)
Huzzah! Your GameObject is now gone! So how do you get it back? That process, fortunately, is quite simple: just copy and paste all that code for making it vanish beneath the fadeOut segment, change fadeOut to fadeIn, and change the fadeAmount calculation so it adds the new amount to the Alpha rather than subtracts. Change the if(objectColor.a) statement at the bottom to check if the GameObject's Alpha is 1 or above, and change the boolean inside that to fadeIn rather than fadeOut. Finally, add another if(Input) statement so you can test the fading-in effect. Your code should look roughly like this:
Hit A and the GameObject fades out; hit S and the GameObject fades back in. Easy peasy. It's worth noting that there are a few inefficiencies in the code - defining objectColor and fadeAmount twice is a bit redundant, for example - but this will get the job done.
As a solution this works fine, but it has one major flaw: Any time you put code in Update, your game will constantly be checking to see if it is true or not. This isn't a huge problem if you only put a few things in Update, but you can drag your game down quite a bit if you rely too much on checking booleans every frame. Fortunately, there are other, less-costly options available, and the last one we're going to look at is just that.
3. Use a Coroutine
The final method for fading objects in and out involves the use of Coroutines. Coroutines are functions that operate for a set amount of time before ending themselves. They're very handy for timed events, and use up a lot less memory to boot.
Virtually all of the code we used for the Update method still applies here - we just need to relocate it into new wrappers. Take the FadeInObject() and FadeOutObject() functions from earlier and convert them into Coroutines like so:
An IEnumerator is a Coroutine, it just has a different name. Note that both of these functions are registering as errors; this is because a Couroutine must have some measure of time passing within its code to work properly. We'll get to that in a moment.
Once your Coroutines are set up you can then transplant all of the code from your Update booleans directly into the functions, albeit with some tweaking. Rather than using fadeIn / fadeOut booleans, we're now going to use While() statements to determine when the Coroutine needs to stop altering the color of your GameObject. The same conditions as above will still apply. While() statements are quite powerful, and can freeze Unity completely if you don't code them properly, so make sure you get this part right!
At the end of each While() statement you also need to add an extra line: 'yield return null'. yield return is a Coroutine-specific command that tells Unity to stop execution of the code for a specified period of time. In this case, it's telling Unity to halt execution completely, at which point the While() statement loops back to the beginning and fades out your GameObject a little more. Once the requirements of the While() statement is completed the Coroutine will move past 'yield return null' and end.
Almost done. Now we just need to tinker with the if(Input) statements. They still trigger the functions, as above, but in order to trigger Coroutines you need to add something extra: StartCoroutine(). If you don't put the function in brackets it won't start. (Note that you still need the two extra function brackets inside the Coroutine's brackets. They're easy to forget.)
Your completed code should look like this:
The changes to your original code are less drastic than they might initially seem, and the results are nigh-identical: The A key makes your GameObject disappear, and the S key makes your GameObject reappear. You can also add a boolean that prevents you from activating either of the functions until the object is completely visible or completely invisible, though this should only be necessary if the player is able to trigger the fade in / fade out effects on their own.
You can now use these functions in other scripts to call on GameObjects for a disappearing act, or relocate the code entirely to a master script that targets specific GameObjects and makes them disappear. As long as an object has a Renderer of some kind, it should vanish on command.
© 2020 Matt Bird