Плавний екран завантаження між сценами


14

Я створив екран завантаження, щоб відобразити завантажувальну анімацію, коли наступна сцена завантажується. Я завантажую наступну сцену асинхронно з:

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

І також встановити Application.backgroundLoadingPriority = ThreadPriority.Low;, але поведінка все одно така, як і звичайне навантаження рівня.

Я щось пропускаю?

Очікувана поведінка:

  • Вийдіть на рівень і згасайте.
  • З'явиться екран завантаження.
  • Після того, як завантаження виконано, зникає екран завантаження.
  • Зникають у наступній сцені.

Що відбувається:

  • Вийдіть на рівень і згасайте.
  • З'явиться екран завантаження, заморожений
  • Раптом нова сцена стихає.

Як тільки завантаження починається, гра просто заморожується, як і звичайне завантаження сцени.

Я прочитав, що ви повинні встановити allowSceneActivation = false, щоб ви могли вимкнути екран завантаження, а потім встановити його, trueщоб дозволити єдності закінчувати завантаження, але це повністю застигає мою гру, так як операція асинхронізації ніколи не закінчує завантаження.


У мене була ця проблема і тут нічого не знайшли. Після гугла я з'ясував, що викликає це питання. Я вирішив опублікувати його тут, щоб інші могли легко знайти відповідь. Будь ласка, дайте мені знати, чи можете ви додати якісь вдосконалення до моєї відповіді / запитання. Спасибі!
Лев

Відповіді:


18

Коли ви завантажуєте сцену SceneManager.LoadSceneAsync(), насправді відбувається дві речі:

  • Ігрові об’єкти сцени завантажуються в пам'ять.
  • Потім увімкнена вся сцена. Усі зворотні дзвінки Awake () та Start () будуть викликані для об'єктів у сцені.

Другий крок, що дозволяє створити сцену, - це те, що фактично заморожує єдність, оскільки єдність виконує всі ці зворотні виклики ініціалізації у ваших сценаріях за один цикл.

Дійсно, налаштування SceneManager.LoadSceneAsync().allowSceneActivationна falseзмусить операцію асинхронізації виконати лише перший крок процесу, і чекатиме, поки не встановлено, trueщоб розпочати другу частину процесу.

Але якщо ви встановили allowSceneActivationв falseі вихід на зворотний виклик , як це, ви будете заморожувати свою гру на благо:

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

//Fade the loading screen out here

AO.allowSceneActivation = true;

Чому? Тому що ви говорите операції Async не продовжувати другий крок завантаження сцени, тому операція ніколи не буде завершена.

Якщо ви хочете знати, коли перша частина операції готова, щоб потім продовжити другу, вам доведеться покластися AsyncOperation.progress. Це значення припиняється, як 0.9fтільки він чекає allowSceneActivationпрапора.

Це має бути приблизно так:

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;

Якщо ви хочете, щоб активація сцени не заморожувала вашу гру, тоді вам слід звести зворотний зв'язок Awake і Start до мінімуму та ініціалізувати свої сценарії в підпрограмі через кілька циклів.


0

У мене був такий самий випуск у Unity 5.6, і я вже намагався додавати у звіті про прибутки. Саме LoadSceneAsync блокував основну нитку Unity і заважав поточній сцені добре показувати будь-який прогрес завантаження.

Наскільки я можу сказати, це помилка в Unity. Коли моя сцена була менш складною, мій код спрацював чудовий, плавний перехід. Як тільки вона збільшилася, Unity блокував нитку приблизно на 6 секунд, весь цей час гра виглядає як "не реагує", незважаючи на те, що операція нібито "асинхронізується"

Те, як я вирішив це питання, - це подивитися на своє освітлення. У минулому були масивні помилки з освітленням і цією особливістю. Тож я переглянув свої об’єкти і виявив, що у мене є прожектор на одному об’єкті (навіть якщо він був відключений ...)

Я видалив прожектор, і ура! Сцена завантажує асинхронізацію належним чином! Без блокування!


До редагування ця публікація насправді не пропонувала рішення проблеми. Зараз добре, що ви додали виправлення, але в майбутньому, якщо ви хочете сказати "У мене це питання теж", ви не повинні використовувати відповіді для цієї мети. Заробивши невелику репутацію, ви зможете коментувати наявні публікації, або ставити щедру питання, щоб заохотити нові відповіді.
DMGregory
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.