Переходы между сценами
API `scene.transition()` — анимированная передача управления между сценами с одновременной работой обеих сцен в момент наложения.
scene.start(key) переключает сцены жёстко — shutdown уходящей сцены срабатывает раньше, чем create входящей. scene.transition({...}) даёт окно наложения, в котором обе сцены работают вместе — идеально для перекрёстных затуханий (crossfade), въездов (slide-in) и эффектов «сдвинуть одну сцену за пределы экрана, пока следующая въезжает».
Форма вызова
this.scene.transition({
target: 'Game', // ключ сцены, которую нужно ввести
duration: 600, // мс — в течение этого времени работают обе сцены
sleep: false, // если true, эта сцена засыпает (с возможностью возобновления); иначе shutdown
remove: false, // если true, эта сцена полностью удаляется
moveAbove: true, // отрисовывать целевую сцену поверх этой
allowInput: false, // отключить ввод на этой сцене во время перехода
onUpdate: (progress) => { /* вызывается каждый кадр, 0..1 */ },
});
Читается так: «запусти Game параллельно со мной; в течение следующих 600 мс вызывай onUpdate со значением прогресса; когда переход завершится, сделай со мной X (sleep / shutdown / remove)».
init и create целевой сцены срабатывают немедленно. Её update выполняется каждый кадр начиная с нулевого кадра перехода. Уходящая сцена тоже продолжает обновляться (если только вы не остановите её из onUpdate).
Crossfade (перекрёстное затухание)
Самый распространённый паттерн. Твином снижаем alpha уходящей сцены, пока alpha входящей сцены растёт.
// В уходящей сцене:
this.scene.transition({
target: 'Game',
duration: 500,
moveAbove: true,
allowInput: false,
onUpdate: (progress) => {
this.cameras.main.setAlpha(1 - progress);
},
});
// create() входящей сцены:
create() {
this.cameras.main.setAlpha(0);
this.scene.get('Title').events.once('transitionout', () => {
// Уходящая сцена завершена — при необходимости выполните очистку.
});
// Прогресс перехода доступен в `this.scene.systems.settings.transitionProgress`
// в течение окна наложения; alpha камеры этой сцены может зеркалить его.
}
Если обе сцены зеркалят прогресс, получается настоящий crossfade — входящая сцена поднимается от alpha 0, пока уходящая опускается.
Slide-in (въезд)
this.scene.transition({
target: 'Pause',
duration: 400,
sleep: true, // приостановить эту сцену; возобновим её после закрытия Pause
moveAbove: true,
onUpdate: (progress) => {
// Вдвигаем сцену паузы справа.
const pause = this.scene.get('Pause');
pause.cameras.main.scrollX = (1 - progress) * this.scale.width;
},
});
sleep: true — это ключевой приём: когда сцена паузы закрывается (this.scene.stop() изнутри неё), Phaser пробуждает эту сцену, а не создаёт её заново. Это снимает всю проблему «сохранения состояния при переключении сцен».
События, генерируемые во время перехода
| Событие | Где | Когда |
|---|---|---|
transitionout | events уходящей сцены | Когда начинается переход. |
transitioninit | events целевой сцены | После init целевой сцены, до create. |
transitionstart | events целевой сцены | После create целевой сцены. |
transitioncomplete | events целевой сцены | Когда окно перехода завершается. |
this.events.once('transitioncomplete', () => {
this.cameras.main.setAlpha(1); // гарантируем полную видимость
});
Когда использовать transition, а когда start или launch
| Чего хотите | Используйте |
|---|---|
| Жёсткая склейка, замена текущей сцены | scene.start(key) |
| Запустить другую сцену параллельно, бессрочно (HUD, фоновая музыка) | scene.launch(key) |
| Анимировать переключение с наложением | scene.transition({...}) |
| Анимировать переключение без наложения (склейка + анимация появления в новой сцене) | scene.start + camera.fadeIn в новой сцене |
«Переключение» на основе затухания, показанное в examples/scene-transition, — это вариант без наложения: затухание, переключение, появление. Он проще и подходит для большинства случаев. Используйте scene.transition(), когда нужно, чтобы обе сцены отрисовывались одновременно.
Типичные ошибки
Забыть про allowInput: false. Во время наложения обработчики ввода обеих сцен активны. Клик по кнопке в уходящей сцене вызовет её обработчик — обычно это не то, что нужно. Установка allowInput: false на уходящей сцене во время перехода предотвращает это.
Устаревшее состояние при возобновлении. Если использовать sleep: true, то create сцены не запускается заново при возобновлении. Сбрасывайте временное состояние вместо этого в обработчике события 'wake':
this.events.on('wake', () => {
this.timer = 0;
this.player.setVelocity(0);
});
Очистка при remove: true. Установка remove: true немедленно уничтожает display list уходящей сцены. Если во время перехода у вас был твин, пишущий в этот display list, он выдаст ошибку, когда цели исчезнут. Для анимированной передачи используйте семантику sleep или shutdown.
Связанное
- Сцены — жизненный цикл, параллельные сцены, передача данных.
- Камеры —
fadeIn/fadeOutдля более простых переходов без наложения. - examples/scene-transition — запускаемое переключение на основе затухания.