- Home /
Reloading scene asynchronously causes stutter as the scene seems to restart a few times in a row.
I have a project with a single scene. When my player dies I reload the scene. I've tried reloading the scene asynchronously, as in:
Application.LoadLevelAsync(Application.loadedLevel);
But both in the editor and iOS what ends up happening is the scene seems to star over 3 times in a row. That is, the scene shows up on screen and a UI animation stars (which is the first thing that happens in my scene), but immediately the scene restarts 2 more times, until the 3rd time, where the scene does stay loaded and the rest of the game proceeds as usual.
The only thing I gathered so far is that when running on iOS, when this stutter / multi reload happens, I get the following in the Xcode console:
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 65)
Built-in UI layer disabled. Causes: [Requires OpenGL]
If instead I load the scene synchronously, it takes longer to load but I get the scene restarting only once, as I'd expect. Also, on a side note, debug mode seems enabled even though I'm making a release build :/
Any thoughts?
Just in case, here is what I assume is the relevant code. This is the code that kills the player and restarts the level, attached to a 'trap' object that the player can collide with:
IEnumerator killPlayer(GameObject player) {
player.transform.parent.gameObject.GetComponent<PL.Model.Vehicle>().Destroy();
player.transform.parent.gameObject.GetComponentInChildren<AnnouncementsUI>().announce("GAME OVER");
yield return new WaitForSeconds(1.5f);
AsyncOperation reload = Application.LoadLevelAsync(Application.loadedLevel);
reload.allowSceneActivation = false;
// Scene fades to grayscale:
ColorCorrectionCurves[] curves = player.transform.parent.gameObject.GetComponentsInChildren<ColorCorrectionCurves>();
int curvesDone = 0;
while (curvesDone != curves.Length) {
foreach (ColorCorrectionCurves curve in curves) {
curve.saturation = Mathf.Lerp(curve.saturation, 0f, Time.deltaTime);
if (curve.saturation <= 0.01f) {
curvesDone++;
}
}
yield return null;
}
// Application.LoadLevel(Application.loadedLevel);
reload.allowSceneActivation = true;
}
And this is the code that triggers the first animation when the level starts:
public class AnnouncementsUI : MonoBehaviour {
public Text announcement;
public Driver driver;
private Animator animator;
private int announceState;
public bool startGame;
void Start() {
driver.autoThrust = false;
animator = announcement.GetComponent<Animator>();
announceState = Animator.StringToHash("CountDown");
}
void Update() {
if (startGame) {
startGame = false;
StartCoroutine(CountDownToGame(3));
}
}
public IEnumerator CountDownToGame(int count) {
for (int i = count; i > 0; i--) {
announce(i.ToString());
yield return new WaitForSeconds(1f);
}
announce("Go!");
driver.autoThrust = true;
}
public void announce(string text) {
announcement.text = text;
animator.Play(announceState, -1, 0f);
}
}
Could you post more of the code that does the async load? Is it the same as your last question?
yeah it's the code from the last question. I made a new question cause assu$$anonymous$$g this is like SO, questions should be very focused. Assume that I removed that while you suggested I remove (which btw, I still think it should work with the while but thats' a different story). So the level loading happens every time. What I see is first that the animations taking place while the level loads are definitely being affected by the background loading of the scene, and when the scene is finally done loading, it shows up on screen, starts the first animation and stutters, then reloads the scene again and again and finally allows the scene to keep going.
Got it. And as a side note, indeed, UA is literally SO for Unity (used to even be on StackExchange). And I agree, that while loop should absolutely work, but .progress being wrong is a bug in Unity that has to be worked around.
Could you try putting a print right before the LoadLevelAsync to deter$$anonymous$$e whether it's getting called multiple times or the problem is somewhere else?
The following won't fix but may help. Remove the Update and startGame. You don't really need it and just add:
private bool sentinel = false;
public void SetStartGame
{
StartCoroutine(CountDownToGame(3));
}
private IEnumerator CountDownToGame(int count) {
if(sentinel == true){
Debug.Log("$$anonymous$$ultiple calls");
yield break;
}
for (int i = count; i > 0; i--) {
announce(i.ToString());
yield return new WaitForSeconds(1f);
}
announce("Go!");
driver.autoThrust = true;
sentinel = false;
}
Answer by saldavonschwartz · Jun 25, 2015 at 12:06 PM
Pretend this never happened...
Basically the problem was that I was starting killPlayer
(the coroutine) from OnTriggerEnter
and the method was firing 3 times (most probably because of the DontGoThruThings
approach, aka, raycasting to get collisions at higher speeds). Since StartCoroutine
can be called multiple times, each time dispatching a new copy of the routine, I was literally dispatching 3 routines, each loading the level again.
Your answer
Follow this Question
Related Questions
Loading Progress using UNET 2 Answers
Loadlevel.async stops at ~90%? 4 Answers
Loading Scene in between two scene for web player. 0 Answers