By leaving the loading progress at 0.9f, Unity provides a small buffer that allows the engine to complete any final processing tasks before the scene is fully activated, which helps to prevent any frame rate drops or other issues. The reason for this is that once the scene is activated, it can cause a spike in the frame rate and introduce frame rate drops, which can be noticeable to the player and negatively impact the game experience.
That 0.9 loading thing happens when you set allowSceneActivation to false. For some reason Unity has implemented this so that 0 to 0.9 is for loading the data (which can happen pretty much instantly on a desktop PC) and 0.9 to 1 is for setting up the scene/gameobjects etc, which might take more time...
@@CoolModderJaydonX It happens instantly because your scene does not require too much loading. If you keep "AllowSceneActivation = true", the scene will load once it reaches 1. If you turn it to false, it will stay stuck at 0.9, and wait for you to tell it "AllowSceneActivation = true".
@@log_zero_fox182 I think it was even worse before because I used a while loop instead of a do-while loop, basically doing nothing to help with the loading.
the target is not needed once you make fill amount 0 every time u load the scene.,, and nice work btw, plus u make it easy and pretty much explain everything needed .thanks
if anyone else watching this is noticing that one frame from the last scene appearing when the next one is loaded (almost unnoticeable but annoying) - i added a delay of the time equivalent of one frame at the end after activating the new scene but before disabling the canvas holding the loading screen and that seems to have solved it. not sure if this is the best way to go about it, please tell me if there is a better one!
Great Tutorial. I do feel like I have missed one important piece though. How do you manage your scenes? I added the part about how to switch to another scene but I am interested in something a bit more advanced. I would be interested in seeing a video where you create a menu for a game, then proceed to other scenes.
Thank you for the good presentation. Absolutely very clear and to the point explanation. If possible, please make a video on different types of material and apply the effects on it. As you already used in your videos. or you can say tips to make the environment clear and catchy.
Hi, not sure if I'm missing something basic but if you remove the two artificial delays the method throws a warning about not running asynchronously since there is no longer an await call?
This is really great, just have some questions though. How are you managing your camera and event system objects between scenes? mine appears to whinge that there are multiple of event systems and audio listeners. Presumably I have to disable one, perhaps keep it persistent from the main screen? Interested to get your thoughts.
Thanks for the video. Correct me if I'm wrong but 1:20 creating such singleton pattern where one calls Destroy on gameobject isn't actually going to always work how one would expect. If you call Destroy, it will destroy the object at the end of that frame, so Start and such will run on to be destroyed object (if your MB has such), unless you have some guard variable to check (wasDestroyed) to make sure that those don't run.
If you forget the f for float part of "while (scene.progress < 0.9f);" you can waste a solid 10 minutes trying to work out why the load bar is flickering, the next scene doesn't load and clicking button multiple times adds more do not destroy items! Enjoy
Hey TaroDev, thanks for the awesome tutorial. I just have a quick question regarding the program. For some reason my script requires that I include the "await Task.Delay()" line else the loading canvas doesn't get enabled, which is odd because the scene takes more than 7 seconds to change after clicking the button. Do you know why this is happening? Any pointers would be helpful. Thanks!
I believe this is because the LoadScene() method is flagged as async which expects the method to await something . This is similar to the Unity coroutine which expects a yield return to occur in the coroutine. To remedy the issue, try lowering the value in the await Task.Delay() to something like 1 in the do/while loop and remove the Task.Delay(1000) he had added to slow down the transition between scenes(Since the loading scene was small resulting in a quick load time). You can read more about async here: docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/
Hello. Your comment is fresh so you might have solved the problem I am facing. "Not a developer, just trying to make my game run." await Task.Delay is giving me error. It's saying "Task does not exists in the current context." please help
I dont want the progress bar to load the scene once its reached 90%. I want to make the progress bar to go 100% first and when its 100%, a button appears in which the user will click it and it will then go to the scene. The progress bar looks ugly stopping at 90%. How do i make it reach at 100%?
Can do it something like this code I used in a prototype project.. Sets the bar to 90% then once loading is actually 100% completed updates the bar and leaves a small delay. You'd need to add Tarodev's ActivateScene etc.. public int sceneToLoad = 1; public float loadingUIDelaySecs = 0.1f; public void LoadLevel() { StartCoroutine(AsyncLoad(sceneToLoad, loadingUIDelaySecs)); } IEnumerator AsyncLoad(int sceneIndex, float delaySecs) { yield return new WaitForSecondsRealtime(delaySecs); AsyncOperation operation = SceneManager.LoadSceneAsync(sceneIndex); Debug.Log("Async Loading Started"); while (!operation.isDone) { float progress = operation.progress; Debug.Log(progress); UpdateSlider(progress); yield return null; } Debug.Log("AsyncLoad completed | SceneIndex:" + sceneIndex); yield return new WaitForSecondsRealtime(delaySecs); UpdateSlider(1f); //Gives the effect of 100% completion just before starting the round //Could use DOTween to smooth this but surely we have better things to work on (>_
My problem is, on play (or in build) the load bar goes to 100% in a second and then freezes when loading next scene, so async is not really working, anyone with this problem?
How to change the scene, keepint the UI elements that a singleton class need? I mean , I hate to use Singleton ,one of the reason , When you change scenes, all objects from the previous scene are destroyed and new objects are created for the current scene. However, if you have an object with a Singleton that is not destroyed (using DontDestroyOnLoad), any references to scene-specific objects in that Singleton will still point to the previous scene's objects, which no longer exist. For example, if your ScoreManager has a reference to a Text to display the score, this reference will be valid in the scene where the ScoreManager was created. But when changing scenes, that Text reference will no longer be valid, because that specific Text object no longer exists in the new scene.
Here is the thing... I LOVE to code. That said, I suck. I really really suck at coding. You operate at many levels above my ability. I know I need to know this stuff but no idea how to get from a-z... Like, what is an async function? So many things you assume we/I know lol I suppose, I will simply keep at it until your tuts make sense to me
public async void LoadScene (string 3008) { _target = 0; _progressBar.fillAmount = 0; On the first line I'm getting the following errors: error CS1001: Identifier expected error CS1003: Syntax error, ',' expected And I have no idea why this is happening
I love your videos. This channel is perfect. But I'm new to Unity and C# and I wanna know something. Why are you putting "_" in front of the variable names? I don't know if I expressed myself correctly?
A good naming convention can give you clear, readable code. I use _pascalCase for private variables, CamalCase for public variables and pascalCase (no underscore) for local variables. You should be able to read a snippet of code and know exactly what that variable sits.
@@Tarodev This is excellent, I'm adopting this convention immediately. I noticed you underscored the _Scripts folder aswell - but I don't see how the same logic would apply there? Wait a minute... I vaguely remember something about underscore prefixed folders appearing higher in the hierarchy? Is that right? I tried to look it up, but it seems my search-fu isn't up to the task.
@Gustavo Dario Dominguez @@ammarahmed3432 I've spent nearly 4 hours on this and it still won't work properly (total unity noob here btw). But i figured some things out, maybe this will help: - to make the Buttons work right, attach the "ChangeSceneButton" script file from the Project folder to the "Button" in the Hierarchy. Then drag the "Button" from the Hierarchy onto the Buttons OnClick Component in the Inspector. Then you get a list of functions. Choose > ChangeSceneButton > ChangeScene (string) and type "Scene 2" in the field below (and in the second Scene type "Scene 1" to go back.) My mistake was dragging the script from the Project Folder into the Inspector, which only gave 1 function called "string name" which didn't do anything). - make sure you add both scenes to the Build Settings (go to > File > Build Settings and then click add open scenes, or drag and drop them from the Project folder into the Build Settings window.) hope that helps! loader bar still won't work for me, but at least i can switch scenes now. unity. smh.
cause some fellow gamedevs are def lazy like I am //I used a slider not an image for mine but it should work just as well with an image using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; using System.Threading.Tasks; public class LevelManager : MonoBehaviour { public static LevelManager instance; [SerializeField] private GameObject _loaderCanvas; [SerializeField] private Slider _progressSlider; private float _target; private void Awake() { if(instance == null) { instance = this; DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); } } public async void LoadScene(string sceneName) { _target = 0; var scene = SceneManager.LoadSceneAsync(sceneName); scene.allowSceneActivation = false; _loaderCanvas.SetActive(true); do { await Task.Delay(1000); //artifical wait time _progressSlider.value = scene.progress; } while(scene.progress < 0.9f); //await Task.Delay(1000); scene.allowSceneActivation = true; _loaderCanvas.SetActive(false); } private void Update() { _progressSlider.value = Mathf.MoveTowards(_progressSlider.value, _target, 3 * Time.deltaTime); } }
Instead a do while loop, we could loop as long the scene is not yet loaded. Unity uploaded a video of doing this way: ua-cam.com/video/zObWVOv1GlE/v-deo.html
Yes, you would have to create a "loading screen caller" (a script that calls the singleton), and add it to all of your scenes. That way, you could have your main loading screen script on, let's say on your main menu, and once you load a different scene, you would be able to call that loading screen, since there's a script on that scene that calls it. Another approach could be using Game Events.
I think your videos show a high level of skill with programming, but you're a lousy teacher. You simply can't do 5 other things not related to the task you're teaching. Every time you create any kind of special variable, function, you need to reference that to other videos which describe in depth that task separately. This is how you can choose your next videos. Every single logic in your code needs its own unique video, and it needs to be explicitly acknowledged. Also, tying all your videos into a single large project helps immensely. Too many videos start already with a setup situation that the viewer may not relate to.
Valid points and something I'm slowly starting to improve (I've been told once or twice I need to explain certain lines a bit clearer). A major component of not doing it is because I'm trying to make my videos short and to the point... Explaining every line would make each video 30 minutes long, which is the opposite of what I wanted for the channel. For example I don't fill my videos begging for subs or shove any unessersary life story in your face as I don't want to waste your time. I'll keep this in mind as it's good advice. From now on if I write a special line I'll either link to another video of mine or somebody else's. Thanks for taking the time to give valuable feedback 👍
By leaving the loading progress at 0.9f, Unity provides a small buffer that allows the engine to complete any final processing tasks before the scene is fully activated, which helps to prevent any frame rate drops or other issues. The reason for this is that once the scene is activated, it can cause a spike in the frame rate and introduce frame rate drops, which can be noticeable to the player and negatively impact the game experience.
Thanks man for the clear explanation! 🌹
That 0.9 loading thing happens when you set allowSceneActivation to false. For some reason Unity has implemented this so that 0 to 0.9 is for loading the data (which can happen pretty much instantly on a desktop PC) and 0.9 to 1 is for setting up the scene/gameobjects etc, which might take more time...
Hi, I know this is a year old, but does this mean that if I keep allowSceneActivation to be true throughout, I can use 0 to 1 instead of to 0.9?
@@Katubug Yes, that's what is implied
Why does that happen instantly?
@@CoolModderJaydonX It happens instantly because your scene does not require too much loading. If you keep "AllowSceneActivation = true", the scene will load once it reaches 1. If you turn it to false, it will stay stuck at 0.9, and wait for you to tell it "AllowSceneActivation = true".
@@log_zero_fox182 I think it was even worse before because I used a while loop instead of a do-while loop, basically doing nothing to help with the loading.
super-useful you deserve way more subs
This is what i am looking for. This tutorial solved my almost every problem
You just continue to provide the absolute best content for unity on here. Bravo!
the target is not needed once you make fill amount 0 every time u load the scene.,, and nice work btw, plus u make it easy and pretty much explain everything needed .thanks
@tarodev keep up the good work very informative tutorials!!!
great tutorial man
Thank you man. You're so good. ✌
if anyone else watching this is noticing that one frame from the last scene appearing when the next one is loaded (almost unnoticeable but annoying) - i added a delay of the time equivalent of one frame at the end after activating the new scene but before disabling the canvas holding the loading screen and that seems to have solved it. not sure if this is the best way to go about it, please tell me if there is a better one!
Great Tutorial. I do feel like I have missed one important piece though. How do you manage your scenes? I added the part about how to switch to another scene but I am interested in something a bit more advanced. I would be interested in seeing a video where you create a menu for a game, then proceed to other scenes.
Yep! I am having a problem with how to connect two scenes "Main Menu" and "Gameplay" to work together with all the buttons and stuff...
Thank you for the good presentation.
Absolutely very clear and to the point explanation.
If possible, please make a video on different types of material and apply the effects on it. As you already used in your videos. or you can say tips to make the environment clear and catchy.
Very good tut, helped a lot
Thank you! Great lesson!
straight to the point. great tutorial
Yes mate ! solid content, keep it coming please, thanks, ok bye.
Nice and clear……thanks!
Really cool. Thanks!
Maybe I missed it, but somehow I forgot to put using UnityEngine.SceneManagement; at the top level and without it was obviously getting errors.
How do i setup the loading screen canvas?
Hi, not sure if I'm missing something basic but if you remove the two artificial delays the method throws a warning about not running asynchronously since there is no longer an await call?
If you guys get Error CS0103 : The name 'Task' does not exist in the current context
then put this
await System.Threading.Tasks.Task.Delay(100);
This is really great, just have some questions though. How are you managing your camera and event system objects between scenes? mine appears to whinge that there are multiple of event systems and audio listeners. Presumably I have to disable one, perhaps keep it persistent from the main screen? Interested to get your thoughts.
Sadly the effect on my end is "it just loads once' lol idk what am I doiing wrong
Thanks for the video. Correct me if I'm wrong but 1:20 creating such singleton pattern where one calls Destroy on gameobject isn't actually going to always work how one would expect. If you call Destroy, it will destroy the object at the end of that frame, so Start and such will run on to be destroyed object (if your MB has such), unless you have some guard variable to check (wasDestroyed) to make sure that those don't run.
I just tested this by placing breakpoints in start and it never hits (v2020.3.13f1). Maybe in an older version of Unity this happened?
@@Tarodev Maybe I've simply messed up something in my code earlier! Go figure. Anyway - great if it works!
@@Tarodev it will never hit unless you add 2 objects with same script this snipped should remove the second one
If you forget the f for float part of "while (scene.progress < 0.9f);" you can waste a solid 10 minutes trying to work out why the load bar is flickering, the next scene doesn't load and clicking button multiple times adds more do not destroy items! Enjoy
thank you sir. but, i wanna ask about, can we randomly load a different loading image screen to another random stage scene?
Thanks a lot!
Hey TaroDev, thanks for the awesome tutorial. I just have a quick question regarding the program. For some reason my script requires that I include the "await Task.Delay()" line else the loading canvas doesn't get enabled, which is odd because the scene takes more than 7 seconds to change after clicking the button. Do you know why this is happening? Any pointers would be helpful. Thanks!
i AM DEALING WITH THE SAME PROBLEM
@@PeaceLifeHealing I think it it is needed in the "Do" part of the script, but this is the one after the "while" that should not be there.
I believe this is because the LoadScene() method is flagged as async which expects the method to await something . This is similar to the Unity coroutine which expects a yield return to occur in the coroutine. To remedy the issue, try lowering the value in the await Task.Delay() to something like 1 in the do/while loop and remove the Task.Delay(1000) he had added to slow down the transition between scenes(Since the loading scene was small resulting in a quick load time).
You can read more about async here:
docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/
Hi, is there any way to switch to scene 0? I tried it but it ended up unloading the scene.
You can set the _target to 1 after the while loop so the progress bar goes all the way
Hello. Your comment is fresh so you might have solved the problem I am facing.
"Not a developer, just trying to make my game run." await Task.Delay is giving me error. It's saying "Task does not exists in the current context." please help
@@muhammahnumanmughal7817 try removing async from the function name and getting rid of await Task.Delay
I dont want the progress bar to load the scene once its reached 90%. I want to make the progress bar to go 100% first and when its 100%, a button appears in which the user will click it and it will then go to the scene. The progress bar looks ugly stopping at 90%. How do i make it reach at 100%?
nevermind. I solved it
@@darrylwolfe7359 how dont just say nvm say it lmao
@@arcanep They probably just multiplied the progress value by "1/0.9" to scale it from (0;0.9) interval to (0;1) interval
Can do it something like this code I used in a prototype project.. Sets the bar to 90% then once loading is actually 100% completed updates the bar and leaves a small delay. You'd need to add Tarodev's ActivateScene etc..
public int sceneToLoad = 1;
public float loadingUIDelaySecs = 0.1f;
public void LoadLevel()
{
StartCoroutine(AsyncLoad(sceneToLoad, loadingUIDelaySecs));
}
IEnumerator AsyncLoad(int sceneIndex, float delaySecs)
{
yield return new WaitForSecondsRealtime(delaySecs);
AsyncOperation operation = SceneManager.LoadSceneAsync(sceneIndex);
Debug.Log("Async Loading Started");
while (!operation.isDone)
{
float progress = operation.progress;
Debug.Log(progress);
UpdateSlider(progress);
yield return null;
}
Debug.Log("AsyncLoad completed | SceneIndex:" + sceneIndex);
yield return new WaitForSecondsRealtime(delaySecs);
UpdateSlider(1f);
//Gives the effect of 100% completion just before starting the round
//Could use DOTween to smooth this but surely we have better things to work on (>_
My problem is, on play (or in build) the load bar goes to 100% in a second and then freezes when loading next scene, so async is not really working, anyone with this problem?
me 2
thank u so much.
Idk why but unity wont recognize the word Task after the await :/
Nevermind ! I just forget the System.Threading.Tasks namespace !Ahah
Add 'using System.Threading.Tasks;' to the top of your file.
How to change the scene, keepint the UI elements that a singleton class need? I mean , I hate to use Singleton ,one of the reason , When you change scenes, all objects from the previous scene are destroyed and new objects are created for the current scene. However, if you have an object with a Singleton that is not destroyed (using DontDestroyOnLoad), any references to scene-specific objects in that Singleton will still point to the previous scene's objects, which no longer exist.
For example, if your ScoreManager has a reference to a Text to display the score, this reference will be valid in the scene where the ScoreManager was created. But when changing scenes, that Text reference will no longer be valid, because that specific Text object no longer exists in the new scene.
Error CS0103 The name 'Task' does not exist in the current context
await System.Threading.Tasks.Task.Delay(100);
Here is the thing... I LOVE to code. That said, I suck. I really really suck at coding. You operate at many levels above my ability.
I know I need to know this stuff but no idea how to get from a-z...
Like, what is an async function? So many things you assume we/I know lol
I suppose, I will simply keep at it until your tuts make sense to me
Build how to make editable at runtime
public async void LoadScene (string 3008) {
_target = 0;
_progressBar.fillAmount = 0;
On the first line I'm getting the following errors:
error CS1001: Identifier expected
error CS1003: Syntax error, ',' expected
And I have no idea why this is happening
Variable names cannot start with a number. 3008
@@Tarodev Hey friend! Its me again, ur tutorial is amazing, I learned alot!! Thank you so much, and continue this amazing work!
Cheers from Brazil!
I love your videos. This channel is perfect. But I'm new to Unity and C# and I wanna know something. Why are you putting "_" in front of the variable names? I don't know if I expressed myself correctly?
A good naming convention can give you clear, readable code. I use _pascalCase for private variables, CamalCase for public variables and pascalCase (no underscore) for local variables. You should be able to read a snippet of code and know exactly what that variable sits.
@@Tarodev Thank you for explaining. Love your channel. Keep up the good work!
@@Tarodev This is excellent, I'm adopting this convention immediately.
I noticed you underscored the _Scripts folder aswell - but I don't see how the same logic would apply there?
Wait a minute... I vaguely remember something about underscore prefixed folders appearing higher in the hierarchy? Is that right?
I tried to look it up, but it seems my search-fu isn't up to the task.
@@ironbard4901 Yup, that's why I do it :) It's by far my most accessed folder!
It didn't work for me: the loading bar just shows after the next scene has been loaded. In the meantime the first scene just freezed...unity sucks!
I have the same issue do you solve it
@@ammarahmed3432 yes, i placer most of the code in yhe update function.
@Gustavo Dario Dominguez @@ammarahmed3432 I've spent nearly 4 hours on this and it still won't work properly (total unity noob here btw). But i figured some things out, maybe this will help:
- to make the Buttons work right, attach the "ChangeSceneButton" script file from the Project folder to the "Button" in the Hierarchy. Then drag the "Button" from the Hierarchy onto the Buttons OnClick Component in the Inspector. Then you get a list of functions. Choose > ChangeSceneButton > ChangeScene (string) and type "Scene 2" in the field below (and in the second Scene type "Scene 1" to go back.) My mistake was dragging the script from the Project Folder into the Inspector, which only gave 1 function called "string name" which didn't do anything).
- make sure you add both scenes to the Build Settings (go to > File > Build Settings and then click add open scenes, or drag and drop them from the Project folder into the Build Settings window.)
hope that helps!
loader bar still won't work for me, but at least i can switch scenes now. unity. smh.
too bad it just donw't work. At least it works when U3D loads a light scene that takes 0,1 microsec to load :(
cause some fellow gamedevs are def lazy like I am
//I used a slider not an image for mine but it should work just as well with an image
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using System.Threading.Tasks;
public class LevelManager : MonoBehaviour
{
public static LevelManager instance;
[SerializeField] private GameObject _loaderCanvas;
[SerializeField] private Slider _progressSlider;
private float _target;
private void Awake()
{
if(instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
public async void LoadScene(string sceneName)
{
_target = 0;
var scene = SceneManager.LoadSceneAsync(sceneName);
scene.allowSceneActivation = false;
_loaderCanvas.SetActive(true);
do
{
await Task.Delay(1000); //artifical wait time
_progressSlider.value = scene.progress;
}
while(scene.progress < 0.9f);
//await Task.Delay(1000);
scene.allowSceneActivation = true;
_loaderCanvas.SetActive(false);
}
private void Update()
{
_progressSlider.value = Mathf.MoveTowards(_progressSlider.value, _target, 3 * Time.deltaTime);
}
}
Hey man are you by chance a web dev or have been in the past?
scenemanager not in visual studio
Add "using UnityEngine.SceneManagement" to the top of the file
Cool
Instead a do while loop, we could loop as long the scene is not yet loaded. Unity uploaded a video of doing this way: ua-cam.com/video/zObWVOv1GlE/v-deo.html
Please guys help me, I use you tutorial completely and now i have a big problem with .meta files and nothin will work :(
What do you mean? Not sure what has happened.
Does singleton approach work when we have several different level with a main menu...
Yes, you would have to create a "loading screen caller" (a script that calls the singleton), and add it to all of your scenes. That way, you could have your main loading screen script on, let's say on your main menu, and once you load a different scene, you would be able to call that loading screen, since there's a script on that scene that calls it. Another approach could be using Game Events.
no it does not work in big game
You are so close
Dont follow this tutorial without putting a fallback to get out of the do-while loop. I hit an infinate loop and lost an hours worth of work!
I think your videos show a high level of skill with programming, but you're a lousy teacher. You simply can't do 5 other things not related to the task you're teaching. Every time you create any kind of special variable, function, you need to reference that to other videos which describe in depth that task separately. This is how you can choose your next videos. Every single logic in your code needs its own unique video, and it needs to be explicitly acknowledged.
Also, tying all your videos into a single large project helps immensely. Too many videos start already with a setup situation that the viewer may not relate to.
Valid points and something I'm slowly starting to improve (I've been told once or twice I need to explain certain lines a bit clearer). A major component of not doing it is because I'm trying to make my videos short and to the point... Explaining every line would make each video 30 minutes long, which is the opposite of what I wanted for the channel. For example I don't fill my videos begging for subs or shove any unessersary life story in your face as I don't want to waste your time.
I'll keep this in mind as it's good advice. From now on if I write a special line I'll either link to another video of mine or somebody else's.
Thanks for taking the time to give valuable feedback 👍