Unity Progress Bar

In today’s post, we’ll learn how to make an elegant loading screen in Unity. Loading screens can save a lot of frustration for your players, especially if your game is loading a ton of things into memory and taking a lot of time. It goes without saying that having loading screens in a game will improve the user experience, no matter how little. So, let’s dig in to find out how to make them work in Unity.

Radial Progress Bar by AdultLink - 5. Shaders & Effects. Customizable radial progress bar shader for Unity3D. Allows you to set arc range, minimum and maximum colors, textures, radius, and a few more things. Create HP Bars, Speedometers, rank progress, etc! In this post I’ll explain how to make a radial progress bar using Unity and C#. After going through it you should be able to create a basic radial progress bar using Unity assets, as well as adding simple functionality. This is a continuation of a 2D Progress Bar Tutorial found here. I'm creating a levelling skript and I was wondering if there was a way to create like a progress bar feature with an actual bar if not just a percentage amount of how far they have done the level. If anyone has an idea on how I would go about this please help me Thanks, Jack. Welcome to Unity Answers. The best place to ask and answer questions about development with Unity. To help users navigate the site we have posted a site navigation guide. If you are a new user to Unity Answers, check out our FAQ for more information. Make sure to check out our Knowledge Base for commonly asked Unity questions. If you are a moderator, see our Moderator Guidelines page.

You can access the complete project here on Github if you’d like to follow along.

Why do games stall?

Why do games stall in the first place?

For a game to use resources such as images, audio, text, and everything else, it first has to load them into memory from disk. Generally, disk read/write speeds have been the bottleneck when it comes to speed in computing. So, any operations involving disks run slower than those that don’t (SSD’s have heralded a significant improvement to such speeds as they easily offer speedups of 1100% nowadays, which is why operating systems and games take noticeably less time to load as compared to their slower counterparts, but I digress).

Moreover, memory is a limited resource, especially when it comes to mobile devices. A game has to be mindful of the memory it uses and whether it is efficiently allocated. Thus, if a game knows that it needs to load new resources, and the resources that are already loaded into memory are no longer needed, it unloads the existing ones (to free up some memory) and loads the new ones. Of course, loading resources involves the disk, thereby stalling the game as it waits for those resources to be available.

Setting up

To set up our project, we’ll do the following:

  • Create two empty scenes, and call them SceneA & SceneB. We will be transitioning between these two scenes and showing the loading screen while the transition is happening.
  • Create a scene called StartupScene, where we’ll be setting up the loading screen manager and the screen itself.
  • Fill SceneA with a set of random sprites, and fill SceneB with a different set of sprites. This will ensure that resource loading/unloading will happen while switching between the scenes. The loading screen will show us the progress of the process as it happens.

Scene A. As you can see in the inspector, I created a dummy game object to contain references to a set of random sprites. That will make the game load them.

Scene B. Similar to Scene A, but references a different set of sprites.

Creating the loading screen

The loading screen itself will be a UI canvas with the render mode set to “Screen Space – Overlay” and a high sort order, such as 999. The render mode makes our loading screen cover the entire screen, and the high sort order makes sure it is drawn above other UI canvases that might be present all over the game. Whenever we force the game to load a new scene, we show the loading screen as the new scene is loading asynchronously in the background. Moreover, we’ll make the loading screen consume any input events from the player to stop the input event from propagating and potentially triggering a UI event (like a button click) in the other canvases while the game is loading.

We will design the loading screen to show either a progress bar, a percentage, or both.

We start by creating a new UI canvas and naming it LoadingScreen:

Next, we configure the canvas’s render mode and sort order:

Configuring the canvas’s parameters.

Now, we will construct our loading screen. It will have the following elements:

  • A solid-color background.
  • Text that just says “Loading”.
  • Text that shows the progress percentage as the game loads (“92%” for example).
  • The progress bar.

Unity Progress Bar Asset

For the background, we’ll add the default Unity UI Image game object, stretch it in both directions to make it fill the entire screen, and give it a nice tint.

We’ll add some UI text that says “Loading” somewhere in the bottom. This text will remain unchanged.

We’ll also add some more UI text right next to the static “Loading” text. This text will show the percentage, and so we’ll be modifying its contents later by code.

Finally, the simplest way to create a progress bar is by first adding a UI Image to the canvas, stretching it horizontally to a size that will eventually be the width of the progress bar, and giving it a transparent black-ish tint. This rectangle will be the bar’s background/shadow; the part that will gradually be filled as the game is loading. Similarly, for the fill itself, create another UI image and give it a solid color.

To easily manipulate its size and make it go from filling nothing at 0% to filling the entire background at 100%, make it the child of the bar background game object, set its anchors to stretch in both directions, and set its pivot to (0, 0.5). Setting the pivot this way will make it start from the background’s left edge if its x-scale is set to 0, and end at the right edge if its x-scale is set to 1. Meanwhile, setting the anchors makes it easy to resize the entire bar in case it needs to be tweaked. So, really, all we need to do from code is to play around with its scale!

Of course, if you want a fancier bar like in the GIF below, you can substitute the rectangles for actual sprites. It’s a bit more work, as it might involve some masking, but the overall procedure is the same. If you’d like to know more, please let me know in the comments below.

Also, make sure that the background image (of the whole loading screen, not the progress bar), is set as a raycast target. This will make sure it consumes input events and effectively block other UI, as it ought to.

Now we can be sure no unexpected behavior happens due to input while the game loads.


Programming the loading screen

Now comes the fun part: Programming it so that it functions like a loading screen.

Bar

Add the following script to the loading screen UI canvas:

It should be straightforward. We call the Show() method whenever a new scene is loaded and pass the AsyncOperation, and the loading screen will hide itself when it’s done.

To test it out, I went ahead and created another script called SceneTransitioner, which invokes the load operation and the subsequent scene toggle. I added it to a game object in each scene and set each instance to load the other’s scene. To trigger the load, I also added a button in each scene which simply calls the SceneTransitioner’s method.

Here’s the SceneTransitioner script:

As for the startup scene, I wrote a trivial script that instantly loads Scene A after the loading screen is done initializing. It is important to run the game from the startup scene, because that’s where the loading screen is created.

And that’s all we need to have a functioning loading screen:

A working loading screen!

Polish #1 – Guarantee it shows for some time

The loading is too fast, and in this case, the loading screen may be ironically introducing some annoyance with its quick flashing. Of course, the more resources you have, the slower the loading will become. The same also goes to whether you’re running it on a mobile device or not. In any case, let’s patch it up to make sure it shows at least for some time before disabling it.

We can easily modify the LoadingScreen script to achieve this:

Luckily, Unity allows us to pause the loading operation when it reaches 90% if we want it to. So what we do is make sure it does pause and time the loading. Once the timer exceeds the minimum time we set it show (in this case, one second), we unpause the operation and let it proceed naturally:

Polish #2 – Customize

Let’s add options to hide either the percentage text or the progress bar (or… both?). It’s another easy patch for LoadingScreen:

Loading screen without the percentage.

Polish #3 – Fade in/out

This is where the loading screen becomes really juicy. We’ll modify it to fade in whenever it shows, and fade out whenever it hides. This makes for a very smooth transition and for some good eye candy.

To do this, we shall invoke the help of an animator (the component =D). After creating an animator for the loading screen, we add two animation states, one for fading in and one for fading out, along with an animator trigger for each of the two states.

Let’s first create the fade in (or “Show”) animation. We’ll keep it at the default 60 samples per second, and animate the following properties:

  • Background image alpha, from 0 to 255.
  • Progress bar background image alpha, from 0 to whatever value was chosen as the default.
  • Progress bar fill image alpha, from 0 to 255.
  • “Loading” text alpha, from 0 to 255.
  • Percentage text alpha, from 0 to 255.

Also, somewhere around 30% of the animation length, we add keys to those values, and set them higher than what they’re supposed to be when linearly interpolated. This will give a decent effect whereby the fade in appears to accelerate and then mellow out. As for how much higher, I’ll set them to 60% between their initial and final states; 0.6 x (final – initial) + initial yields the values of those intermediate states:

The fade in animation.

Conversely, we do the same for the fade out (“Hide”) animation, so instead of the values being higher than their linear interpolation equivalents, they are actually lower:


Lastly, we need to modify the code to trigger the fade in animation whenever the loading screen shows, and to trigger the fade out animation whenever the loading screen hides. Moreover, the fade out animation itself should disable the loading screen once it’s done playing.

Triggering the fade animations through code is simple:

To let the fade out animation disable the loading screen once it’s finished, just add an animation event at the last sample and set the function to the Hide method:

Hiding the loading screen via the animation.

And finally, the fruit of our labor:

And that’s how I personally go about with loading screens.

You can go ultra creative on how to design a loading screen. All the UI elements are at your disposal. Here’s an example of a fancier loading screen that I implemented for a freelance gig:

A loading screen with sprite animations. Noice.

I hope this tutorial was of some benefit. If you like it (or not) I’d really appreciate some feedback down below!

Unity Radial Slider

And once again, you can access the entire Unity project right here on Github.