Im trying to make my function call Application.LoadLevel() and wait with execution untill a level is loaded. The script is in C#, and I can’t get it to work.
The script reference says this: “OnLevelWasLoaded can be a co-routine, simply use the yield statement in the function.”
If the script with LoadGame(…) in it isn’t marked with DontDestroyOnLoad(), it will no longer exist when the level is done loading, so it won’t be able to execute your code. If, on the other hand, it is marked with DontDestroyOnLoad, it could just use the OnLevelWasLoaded() call-back directly to detect when it is done.
tomvds, it is marked as DontDestroyOnLoad. I know I can use the OnLevelWasLoaded() method, but I still like to yield the LoadLevel method, as things need to happen after the loading of different scenes and I’d like to not use a huge switch() statement in the OnLevelwasLoaded() method.
The docs say it can be done. I just need to find the syntax I guess.
(Warning: untested, I don’t know if it will work at all).
However, I must add that I don’t really see much advantage using this over just using the OnLevelWasLoaded function itself, but obviously I don’t know the context (and perhaps I don’t dislike switch() as much as I should :P).
Thanks tomvds, I appreciate your suggestion. There is indeed not that much advantage over using the switch. You’re right though using the switch is not a huge problem.
It’s just I wanna know how, or if, this could be done with yield
The OnLevelWasLoaded callback is called after the level succesfully loads. If you need to watch the progress of the level loading (for a load bar or something), then you should be using LoadLevelAsync (new to the 2.6 API).
LoadLevelAsync returns a AsyncOperation, which can be yielded on, as well as inspected and modified.
private IEnumerator LoadGame(string strLevel)
{
Debug.Log("Loading Level");
yield return Application.LoadLevelAsync(strLevel);
Debug.Log("Level Load complete");
}
// Here's how OnLevelWasLoaded works
void OnLevelWasLoaded( int level )
{
Debug.Log( "Level : " + level + " was loaded" );
}
// If you wanted to use OnLevelWasLoaded as a co-routine, it's like this
IEnumerator OnLevelWasLoaded( int level )
{
Debug.Log( "Level : " + level + " was loaded, waiting for 10 seconds" );
yield return WaitForSeconds( 10.0f );
Debug.Log( "Level : " + level + " was loaded 10 seconds ago" );
}
Keep in mind that if the script that LoadGame exists in doesn’t have “DontDestroyOnLoad” set, that 2nd debug message might not ever execute, and OnLevelWasLoaded most certainly won’t.
Also OnLevelWasLoaded doesn’t have to be in the same script as the script that calls LevelLoad, and there can be multiple scripts with OnLevelWasLoaded, they’ll all get called whenever the level changes.
Lastly, unless you’re running a streaming web player, or loading a level from an asset bundle, LoadLevelAsync should be instantaneous, and LoadLevel will either be instantaneous, or it won’t work at all (a streamed level isn’t loaded yet).
Hi Factoid, thanks for your reply. You might be right. It looks like LoadLevelAsync is the function I need. Unfortunately I don’t have the Pro version of Unity so I can’t test.
As I replied to tomvds, the object has DontDestroyOnLoad set.
I think you’re reading the statement on the OnLevelWasLoaded page wrong:
It simply means OnLevelWasLoaded can be a coroutine containing yield, that could be used for something like starting an animation after level load or any other sequence that runs during that level.
You seem to interpret the statement such that OnLevelWasLoaded can yield until a next level is loaded, which is not the case. When a next level is loaded a fresh OnLevelWasLoaded is called (i.e. with DontDestroyOnLoad).
I realize this is an old thread, but I looked everywhere for an answer and couldn’t really find one. Here was my solution. GameResources.IsLevelLoaded is set to true in the loaded level’s Start() function:
public class MyGame : MonoBehaviour
{
void Awake()
{
DontDestroyOnLoad(gameObject);
}
void LoadLevel()
{
GameResources.IsLevelLoaded = false;
Application.LoadLevel("Level");
InvokeRepeating("WaitForLevelToLoad", 0f, .01f);
}
void WaitForLevelToLoad()
{
if (GameResources.IsLevelLoaded)
{
CancelInvoke("WaitForLevelToLoad");
LevelLoaded();
}
}
void LevelLoaded()
{
//Level Code Here
}
}
jmasinteati, I don’t see any good reason for that logic. Why don’t do all you need to do inside scene (i.e. level) and do all that must be done before that - in another loading scene or even do that when editor starts (useful when debugging starting from current scene)