Écran de chargement fluide entre les scènes

14

J'ai créé un écran de chargement pour afficher une animation de chargement pendant le chargement de la scène suivante. Je charge la scène suivante de manière asynchrone avec:

yield return SceneManager.LoadSceneAsync(scene,LoadSceneMode.Additive);

Et également défini Application.backgroundLoadingPriority = ThreadPriority.Low;, mais le comportement est toujours le même qu'une charge de niveau régulière.

Suis-je en train de manquer quelque chose?

Comportement attendu:

  • Quittez le niveau et disparaissez.
  • L'écran de chargement apparaît.
  • Une fois le chargement terminé, fondre l'écran de chargement.
  • Fondu dans la scène suivante.

Qu'est-ce qui se passe:

  • Quittez le niveau et disparaissez.
  • L'écran de chargement apparaît, figé
  • Soudain, une nouvelle scène apparaît.

Une fois le chargement démarré, le jeu ne fait que frezees, comme avec un chargement de scène normal.

J'ai lu que vous devez définir allowSceneActivation = false, de sorte que vous puissiez atténuer l'écran de chargement, puis le configurer truepour laisser l'unité terminer le chargement, mais cela gèle complètement mon jeu, comme l'opération asynchrone ne termine jamais le chargement.

Leo
la source
J'ai eu ce problème et je n'ai rien trouvé ici. Après avoir recherché sur Google, j'ai découvert la cause de ce problème. J'ai décidé de le poster ici afin que d'autres puissent trouver facilement la réponse. Veuillez me faire savoir si vous souhaitez apporter des améliorations à ma réponse / question. Merci!
Leo

Réponses:

18

Lorsque vous chargez une scène avec, SceneManager.LoadSceneAsync()il se passe en fait deux choses:

  • Les objets de jeu de la scène sont chargés en mémoire.
  • Ensuite, toute la scène est activée. Tous les rappels Awake () et Start () seront appelés pour les objets de la scène.

La deuxième étape, l'activation de la scène, est ce qui gèle réellement l'unité, car l'unité exécute tous ces rappels d'initialisation dans vos scripts en un seul cycle.

En effet, la définition SceneManager.LoadSceneAsync().allowSceneActivationde falsefera que l'opération asynchrone ne terminera que la première étape du processus et attendra jusqu'à ce qu'elle soit définie truepour commencer la deuxième partie du processus.

Mais si vous définissez allowSceneActivationpour falseet le rendement sur le rappel comme celui - ci, vous geler votre jeu pour le bien:

AsyncOperation AO = SceneManager.LoadSceneAsync(scene,LoadSceneMode.Additive); 
AO.allowSceneActivation = false;
yield return AO;

//Fade the loading screen out here

AO.allowSceneActivation = true;

Pourquoi? Parce que vous dites à l'opération Async de ne pas poursuivre la deuxième étape du chargement de la scène, l'opération ne sera donc jamais terminée.

Si vous voulez savoir quand la première partie de l'opération est prête, pour ensuite passer à la seconde, vous devez vous fier à AsyncOperation.progress. Cette valeur s'arrêtera 0.9fimmédiatement en attendant le allowSceneActivationdrapeau.

Cela devrait être quelque chose comme ceci:

AsyncOperation AO = SceneManager.LoadSceneAsync(scene,LoadSceneMode.Additive); 
AO.allowSceneActivation = false;
while(AO.progress < 0.9f)
{
    yield return null
}

//Fade the loading screen out here

AO.allowSceneActivation = true;

Si vous voulez que l'activation de la scène ne gèle pas votre jeu, alors vous devriez garder vos rappels Awake and Start à un minimum et initialiser vos scripts dans une coroutine à travers plusieurs cycles.

Leo
la source
0

J'avais exactement le même problème dans Unity 5.6, et j'avais déjà essayé d'ajouter dans les déclarations de rendement. C'est le LoadSceneAsync lui-même qui bloquait le thread principal d'Unity et empêchait la scène actuelle de bien montrer la progression du chargement.

Il semblerait que ce soit un bug dans Unity pour autant que je sache. Quand ma scène était moins complexe, mon code fonctionnait très bien, une transition en douceur. Une fois qu'il est devenu plus grand, Unity a bloqué le fil pendant environ 6 secondes, tout le temps que le jeu se trouve comme «ne répond pas» malgré l'opération censée être «asynchrone»

La façon dont j'ai résolu le problème était de regarder mon éclairage. Il y a eu des bugs massifs dans le passé avec l'éclairage et cette fonctionnalité. J'ai donc parcouru mes objets et j'ai découvert que j'avais un projecteur sur un objet (même s'il était désactivé ...)

J'ai supprimé le projecteur, et hourra! La scène se charge correctement en mode asynchrone! Pas de verrouillage!

Seigneur de la pile
la source
Avant la modification, ce message n'offrait pas réellement de solution au problème. C'est bien maintenant que vous avez ajouté un correctif, mais à l'avenir si vous voulez dire "J'ai aussi ce problème", vous ne devriez pas utiliser de réponses à cette fin. Gagner un petit représentant vous permettra de commenter les messages existants ou de mettre une prime sur les questions pour encourager de nouvelles réponses.
DMGregory