Płynny ekran ładowania między scenami

14

Utworzyłem ekran ładowania, aby wyświetlać animację ładowania podczas ładowania następnej sceny. Następną scenę ładuję asynchronicznie za pomocą:

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

I również ustawione Application.backgroundLoadingPriority = ThreadPriority.Low;, ale zachowanie jest nadal takie samo jak zwykłe obciążenie poziomu.

Czy coś brakuje?

Oczekiwane zachowanie:

  • Wyjdź z poziomu i wycisz.
  • Pojawi się ekran ładowania.
  • Po zakończeniu ładowania zniknij ekran ładowania.
  • Zanikaj w następnej scenie.

Co się dzieje:

  • Wyjdź z poziomu i wycisz.
  • Zostanie wyświetlony ekran ładowania, zamrożony
  • Nagle pojawia się nowa scena.

Po rozpoczęciu ładowania gra po prostu zawiesza się, jak w przypadku zwykłego ładowania sceny.

Przeczytałem, że musisz ustawić allowSceneActivation = false, abyś mógł wyłączyć ekran ładowania, a następnie ustawić go tak, trueaby jedność zakończyła ładowanie, ale to całkowicie zawiesza moją grę, tak jakby operacja asynchroniczna nigdy się nie kończy.

Lew
źródło
Miałem ten problem i nic tutaj nie znalazłem. Po googlowaniu dowiedziałem się, co jest przyczyną tego problemu. Postanowiłem opublikować go tutaj, aby inni mogli łatwo znaleźć odpowiedź. Daj mi znać, czy możesz ulepszyć moją odpowiedź / pytanie. Dzięki!
Leo

Odpowiedzi:

18

Kiedy wczytujesz scenę, w SceneManager.LoadSceneAsync()rzeczywistości dzieją się dwie rzeczy:

  • GameObjects sceny są ładowane do pamięci.
  • Następnie cała scena jest włączona. Wszystkie obiekty zwrotne Awake () i Start () zostaną wywołane dla obiektów w scenie.

Drugi krok, włączenie sceny, jest tym, co faktycznie zamraża jedność, ponieważ jedność uruchamia wszystkie wywołania inicjujące w twoich skryptach w jednym cyklu.

Rzeczywiście ustawienie SceneManager.LoadSceneAsync().allowSceneActivationto falsespowoduje, że operacja asynchroniczna zakończy tylko pierwszy krok procesu, i poczeka, aż truerozpocznie się druga część procesu.

Ale jeśli ustawisz allowSceneActivationsię falsei rentowność zwrotnego jak ta, można zamrozić swoją grę na dobre

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

//Fade the loading screen out here

AO.allowSceneActivation = true;

Dlaczego? Ponieważ mówisz operacji Async, aby nie kontynuowała drugiego kroku ładowania sceny, więc operacja nigdy nie zostanie zakończona.

Jeśli chcesz wiedzieć, kiedy pierwsza część operacji jest gotowa, aby przejść do drugiej, musisz polegać AsyncOperation.progress. Ta wartość zatrzyma się 0.9fnatychmiast po oczekiwaniu na allowSceneActivationflagę.

Powinno to być coś takiego:

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;

Jeśli chcesz, aby aktywacja sceny nie zamroziła twojej gry, powinieneś ograniczyć wywołania Przebudź i Rozpocznij do minimum, a także zainicjować skrypty w sposób ciągły przez kilka cykli.

Lew
źródło
0

Miałem dokładnie ten sam problem w Unity 5.6 i już próbowałem dodać w deklaracjach dochodu. To właśnie LoadSceneAsync blokował główny wątek Unity i uniemożliwiał bieżącej scenie ładnie pokazujący postęp ładowania.

O ile wiem, wydaje się, że jest to błąd w Unity. Kiedy moja scena była mniej złożona, mój kod działał świetnie, płynne przejście. Gdy się powiększy, Unity zablokował wątek na około 6 sekund, przez cały czas gra nie reaguje, mimo że operacja ma być „asynchroniczna”

Rozwiązałem ten problem, patrząc na moje oświetlenie. W przeszłości wystąpiły ogromne błędy związane z oświetleniem i tą funkcją. Więc przejrzałem moje obiekty i odkryłem, że mam reflektor na jednym obiekcie (nawet jeśli był wyłączony ...)

Usunąłem reflektor i brawo! Scena ładuje się poprawnie asynchronicznie! Bez blokady!

Władca stosu
źródło
Przed edycją ten post nie oferował rozwiązania problemu. Teraz jest dobrze, gdy dodałeś poprawkę, ale w przyszłości, jeśli chcesz powiedzieć „Mam też ten problem”, nie powinieneś używać w tym celu odpowiedzi. Zdobycie małego przedstawiciela pozwoli Ci skomentować istniejące posty lub wynagrodzić pytania, aby zachęcić do nowych odpowiedzi.
DMGregory