scenes について
Phaser 開発者向けに、シーンのライフサイクル、注入されるシステム、ScenePlugin による複数シーンの管理を解説するリファレンスです。ゲームの流れやシーン遷移、並行実行の整理に役立ちます。
主な機能
- 01シーンのライフサイクルと状態管理
- 02シーン固有および共有システム
- 03シーンの開始、一時停止、休止、再開
- 04シーン間のデータとイベントの受け渡し
活用シーン
- 01レベルやメニューのシーン構成
- 02ゲーム UI シーンの並行実行
- 03シーン遷移時のゲームデータ受け渡し
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ phaserjs/ phaser --skill scenesインストール後、Claude Code で/scenesを入力して読み込まれたか確認します。
同梱ファイルreferences/REFERENCE.md
詳細
シーン
シーンは Phaser ゲームの組織的なバックボーンです。各シーンは独自のライフサイクル (init、preload、create、update) と、独自の注入されたシステム (this.add、this.input、this.cameras など) を持ち、開始、停止、一時停止、スリープ、または他のシーンとの並列実行が可能です。ScenePlugin (
this.scene) がすべてのマルチシーンオーケストレーションを制御します。
主要なソースパス: src/scene/Scene.js、src/scene/Systems.js、src/scene/SceneManager.js、src/scene/ScenePlugin.js、src/scene/Settings.js、src/scene/const.js、src/scene/events/、src/scene/InjectionMap.js
関連スキル: ../game-setup-and-config/SKILL.md、../loading-assets/SKILL.md、../events-system/SKILL.md
クイックスタート
// Minimal scene with all lifecycle methods
class GameScene extends Phaser.Scene {
constructor() {
super('GameScene');
}
init(data) {
// Called first. Receives data passed from other scenes.
// 'data' is whatever was passed via scene.start('GameScene', { level: 1 })
this.level = data.level || 1;
}
preload() {
// Called after init. Load assets here.
this.load.image('logo', 'assets/logo.png');
}
create(data) {
// Called after preload completes. Set up game objects.
// 'data' is the same object passed to init.
this.add.image(400, 300, 'logo');
}
update(time, delta) {
// Called every frame while scene is RUNNING.
// time: current time (ms), delta: ms since last frame (smoothed)
}
}
const config = {
width: 800,
height: 600,
scene: [GameScene]
};
const game = new Phaser.Game(config);
コアコンセプト
シーンのライフサイクル
ライフサイクルは SceneManager.bootScene() と SceneManager.create() によって駆動されます:
- PENDING (0) - シーンは登録されていますが、まだ開始されていません。
- INIT (1) - 定義されている場合、
scene.init(data)が呼び出されます。データはsettings.dataから渡されます。 - START (2) -
Systems.start()が実行されます。startとreadyイベントが発行されます。 - LOADING (3) - 定義されている場合、
scene.preload()が呼び出されます。ローダーが実行されます。完了すると、create へ進みます。 - CREATING (4) - 定義されている場合、
scene.create(data)が呼び出されます。init と同じdataです。 - RUNNING (5) - 毎フレーム
scene.update(time, delta)が呼び出されます。シーンがレンダリングされます。 - PAUSED (6) - update は行われませんが、レンダリングは続行されます。
- SLEEPING (7) - update もレンダリングも行われません。状態はメモリ内に保持されます。
- SHUTDOWN (8) - シーンがシャットダウンされ、システムが
shutdownを発行します。再起動できます。 - DESTROYED (9) - シーンが完全に破棄されます。再起動はできません。
状態定数は Phaser.Scenes にあります: Phaser.Scenes.PENDING、Phaser.Scenes.RUNNING など。
preload が存在しない場合のフロー: init() -> create() -> update() ループ (preload は完全にスキップされます)。
preload が存在する場合のフロー: init() -> preload() -> ローダーが実行 -> create() -> update() ループ。
シーンに注入されるプロパティ
これらのプロパティは InjectionMap (src/scene/InjectionMap.js) を介してすべてのシーンインスタンスに注入されます。左側が Systems のキー、右側がシーンのプロパティ名です。
グローバルマネージャー (すべてのシーンで共有)
| シーンプロパティ | 型 | 説明 |
|---|---|---|
this.game | Phaser.Game | Game インスタンス |
this.renderer | CanvasRenderer | WebGLRenderer | アクティブなレンダラー |
this.anims | Phaser.Animations.AnimationManager | グローバルアニメーションマネージャー |
this.cache | Phaser.Cache.CacheManager | 画像以外のアセット用のグローバルキャッシュ |
this.plugins | Phaser.Plugins.PluginManager | グローバルプラグインマネージャー |
this.registry | Phaser.Data.DataManager | グローバルデータマネージャー (シーン間で共有) |
this.scale | Phaser.Scale.ScaleManager | グローバルスケールマネージャー |
this.sound | NoAudio | HTML5Audio | WebAudioSoundManager | サウンドマネージャー |
this.textures | Phaser.Textures.TextureManager | グローバルテクスチャマネージャー |
シーン固有のシステム(シーンごとに固有)
| シーンプロパティ | 型 | 説明 |
|---|---|---|
this.sys | Phaser.Scenes.Systems | シーンシステム(上書きしないでください) |
this.events | Phaser.Events.EventEmitter | シーン固有のイベントエミッター |
this.cameras | Phaser.Cameras.Scene2D.CameraManager | シーンカメラマネージャー |
this.add | Phaser.GameObjects.GameObjectFactory | ファクトリー:作成して表示リストに追加します |
this.make | Phaser.GameObjects.GameObjectCreator | クリエイター:作成しますが表示リストには追加しません |
this.scene | Phaser.Scenes.ScenePlugin | シーンマネージャープラグイン(start/stop/launch) |
this.children | Phaser.GameObjects.DisplayList | シーンの表示リスト |
this.lights | Phaser.GameObjects.LightsManager | シーンライト(プラグイン) |
this.data | Phaser.Data.DataManager | シーン固有のデータマネージャー |
this.input | Phaser.Input.InputPlugin | シーン入力マネージャー(プラグイン) |
this.load | Phaser.Loader.LoaderPlugin | シーンローダー(プラグイン) |
this.time | Phaser.Time.Clock | シーンの時間/クロック(プラグイン) |
this.tweens | Phaser.Tweens.TweenManager | シーンのトゥイーンマネージャー(プラグイン) |
this.physics | Phaser.Physics.Arcade.ArcadePhysics | Arcade 物理(設定されている場合) |
this.matter | Phaser.Physics.Matter.MatterPhysics | Matter 物理(設定されている場合) |
インジェクションマップのカスタマイズ
// Rename injected properties via scene config
const config = {
key: 'MyScene',
map: {
add: 'makeStuff', // this.makeStuff instead of this.add
load: 'loader' // this.loader instead of this.load
}
};
シーンマネージャー
SceneManager(src/scene/SceneManager.js)はゲームレベルのシステムです。そのメソッドを直接呼び出さないでください。代わりに this.scene(ScenePlugin)を使用してください。SceneManager は次のことを行います:
- シーの順序付き配列を維持します(レンダリング/更新の順序を決定します)
- 各ゲームステップの開始時に操作(start、stop、sleep など)のキューを処理します
- すべての ScenePlugin メソッドはキューに入れられ、即時ではなく(次のフレームで)実行されます
一般的なパターン
シーンの切り替え
// start() -- shuts down current scene, starts target scene
// Current scene gets SHUTDOWN event; target gets full lifecycle
this.scene.start('LevelTwo', { score: 100 });
// restart() -- shuts down and restarts the same scene
this.scene.restart({ score: 0 });
// switch() -- sleeps current scene, starts/wakes target scene
// Current scene state is preserved in memory
this.scene.switch('PauseMenu', { fromScene: 'GameScene' });
// transition() -- animated transition with duration
this.scene.transition({
target: 'LevelTwo',
duration: 1000,
moveAbove: true, // render target above this scene
sleep: false, // false = stop this scene (default), true = sleep it
remove: false, // true = remove this scene from manager after transition
allowInput: false, // allow input on this scene during transition
data: { score: 100 },
onUpdate: function (progress) {
// progress: 0 to 1 over duration
}
});
シーンの並列実行
// launch() -- starts another scene in parallel (does NOT stop current scene)
this.scene.launch('UIScene', { lives: 3 });
// run() -- smart launcher: starts if not running, resumes if paused, wakes if sleeping
this.scene.run('UIScene', { lives: 3 });
// Control render order of parallel scenes
this.scene.bringToTop('UIScene'); // render last (on top)
this.scene.sendToBack('Background'); // render first (behind)
this.scene.moveAbove('GameScene', 'UIScene'); // UIScene renders above GameScene
this.scene.moveBelow('GameScene', 'Background');
this.scene.moveUp('UIScene'); // move one position up
this.scene.moveDown('UIScene'); // move one position down
this.scene.swapPosition('SceneA', 'SceneB');
シーン間でのデータの受け渡し
// Method 1: Pass data via start/launch/restart/switch/wake/run
this.scene.start('LevelScene', { level: 5, score: 1200 });
// In LevelScene:
// init(data) { data.level === 5 }
// create(data) { data.score === 1200 }
// Method 2: Access data later via sys.getData()
// In receiving scene, at any time:
const data = this.sys.getData(); // returns settings.data
// Method 3: Global registry (shared across ALL scenes)
// In Scene A:
this.registry.set('playerHP', 100);
// In Scene B:
const hp = this.registry.get('playerHP'); // 100
// Method 4: Scene-specific data manager
this.data.set('localValue', 42);
this.data.get('localValue'); // 42
// Method 5: Direct scene reference
const otherScene = this.scene.get('OtherScene');
otherScene.somePublicProperty;
// Method 6: Events on the global registry
// In Scene A:
this.registry.events.on('changedata-playerHP', (parent, value, previousValue) => {
// react to change
});
// In Scene B:
this.registry.set('playerHP', 50); // triggers the event in Scene A
一時停止と再開
// Pause: stops update loop, still renders
this.scene.pause(); // pause this scene
this.scene.pause('OtherScene'); // pause another scene
// Resume: restart update loop
this.scene.resume();
this.scene.resume('OtherScene', { message: 'welcome back' });
// Sleep: no update AND no render, but state preserved
this.scene.sleep();
this.scene.sleep('OtherScene');
// Wake: restore from sleep
this.scene.wake();
this.scene.wake('OtherScene', { data: 'here' });
// Stop: full shutdown, clears display list and timers
this.scene.stop();
this.scene.stop('OtherScene');
// Check state
this.scene.isActive('OtherScene'); // boolean
this.scene.isPaused('OtherScene'); // boolean
this.scene.isSleeping('OtherScene'); // boolean
this.scene.isVisible('OtherScene'); // boolean
// Control visibility/activity independently
this.scene.setActive(false); // pause
this.scene.setActive(true); // resume
this.scene.setVisible(false); // hide but still update
this.scene.setVisible(true); // show
実行時のシーンの追加と削除
// Add a new scene dynamically
this.scene.add('BonusLevel', BonusLevelScene, false, { someData: true });
// args: key, sceneConfig, autoStart, data
// Remove a scene entirely (destroyed, cannot be restarted)
this.scene.remove('BonusLevel');
// Spawn multiple instances from one class
for (let i = 0; i < 5; i++) {
this.scene.add('Level' + i, new LevelScene('Level' + i), false);
}
シーン間のイベント通信
あるシーンがカスタムイベントを発行し、別のシーンがそれをリッスンします。発行するシーンは分離されています。
// GameScene emits events
class GameScene extends Phaser.Scene {
collectCoin(coin) {
coin.destroy();
this.events.emit('addScore', 10);
}
}
// UIScene listens (launched in parallel with { active: true })
class UIScene extends Phaser.Scene {
constructor() {
super({ key: 'UIScene', active: true });
}
create() {
this.score = 0;
this.scoreText = this.add.text(10, 10, 'Score: 0');
// Listen for events from GameScene
const gameScene = this.scene.get('GameScene');
gameScene.events.on('addScore', (points) => {
this.score += points;
this.scoreText.setText('Score: ' + this.score);
});
}
}
シーンごとのプラグインの設定
すべてのデフォルトプラグインを無効化します(コアプラグインのみが残ります):
super({ key: 'MinimalScene', plugins: [] });
// No this.load, this.tweens, this.time, this.input, this.data, this.lights
特定のプラグインのみを含めます:
super({ key: 'PreloadScene', plugins: ['Loader'] });
// Only this.load is available; this.tweens, this.time, etc. are undefined
コンストラクターでのシーン設定
シーンごとの物理、ローダー、または事前読み込みファイルのために super() に設定を渡します:
class Level1 extends Phaser.Scene {
constructor() {
super({
key: 'Level1',
physics: { arcade: { debug: true, gravity: { y: 200 } } },
loader: { path: 'assets/levels/1/' },
// 'pack' loads files before preload() runs -- good for progress bar assets
pack: {
files: [
{ type: 'image', key: 'bar', url: 'loaderBar.png' }
]
}
});
}
}
シーンの安全な再起動
状態はコンストラクターではなく init() でリセットします。コンストラクターは一度だけ実行され、init() は開始するたびに実行されます。
class GameScene extends Phaser.Scene {
constructor() {
super('GameScene');
// BAD: this.gameOver = false; -- only set once, not on restart
}
init() {
// GOOD: reset state every time the scene starts
this.gameOver = false;
this.score = 0;
}
create() {
// Clean up on shutdown to avoid stale references
this.events.once('shutdown', () => {
// Clear any arrays holding game object references
this.enemies = [];
});
}
}
イベント
すべてのイベントは this.events(シーン固有の EventEmitter)で発行され、文字列の値を持ちます。this.events.on('eventname', callback) でリッスンします。
ライフサイクルイベント
| イベント文字列 | 定数 | コールバックシグネチャ | タイミング |
|---|---|---|---|
'boot' | Phaser.Scenes.Events.BOOT | (sys) | シーンが最初にインスタンス化されるときに一度(プラグイン用) |
'start' | Phaser.Scenes.Events.START | (sys) | シーンシステムの開始時(プラグイン用) |
'ready' | Phaser.Scenes.Events.READY | (sys, data) | 開始後、ユーザーコード用 |
'create' | Phaser.Scenes.Events.CREATE | (scene) | create() メソッドの実行後、シーンは RUNNING 状態になります |
'preupdate' | Phaser.Scenes.Events.PRE_UPDATE | (time, delta) | 毎フレームの update 前 |
'update' | Phaser.Scenes.Events.UPDATE | (time, delta) | 毎フレームの update 中 |
'postupdate' | Phaser.Scenes.Events.POST_UPDATE | (time, delta) | 毎フレームの update 後 |
'prerender' | Phaser.Scenes.Events.PRE_RENDER | (renderer) | シーンのレンダリング前 |
'render' | Phaser.Scenes.Events.RENDER | (renderer) | シーンのレンダリング後 |
状態変更イベント
| イベント文字列 | 定数 | コールバックシグネチャ | 発生タイミング |
|---|---|---|---|
'pause' | Phaser.Scenes.Events.PAUSE | (sys, data) | シーンが一時停止されたとき |
'resume' | Phaser.Scenes.Events.RESUME | (sys, data) | シーンが再開されたとき |
'sleep' | Phaser.Scenes.Events.SLEEP | (sys, data) | シーンがスリープ状態になったとき |
'wake' | Phaser.Scenes.Events.WAKE | (sys, data) | シーンが復帰したとき |
'shutdown' | Phaser.Scenes.Events.SHUTDOWN | (sys, data) | シーンがシャットダウン中のとき |
'destroy' | Phaser.Scenes.Events.DESTROY | (sys) | シーンが破棄されているとき |
遷移イベント
| イベント文字列 | 定数 | コールバックシグネチャ | 発行元 |
|---|---|---|---|
'transitionout' | TRANSITION_OUT | (targetScene, duration) | 遷移元シーン |
'transitioninit' | TRANSITION_INIT | (fromScene, duration) | 遷移先シーン(init 中) |
'transitionstart' | TRANSITION_START | (fromScene, duration) | 遷移先シーン(create 後) |
'transitionwake' | TRANSITION_WAKE | (fromScene, duration) | 遷移先シーン(スリープから復帰した場合) |
'transitioncomplete' | TRANSITION_COMPLETE | (scene) | 遷移先シーン(完了時) |
ゲームオブジェクトイベント
| イベント文字列 | 定数 | コールバックシグネチャ |
|---|---|---|
'addedtoscene' | ADDED_TO_SCENE | (gameObject, scene) |
'removedfromscene' | REMOVED_FROM_SCENE | (gameObject, scene) |
詳細な API リファレンスの表とソースファイルの対応については、リファレンスガイドを参照してください。
落とし穴とよくある間違い
-
操作はキューに入れられ、即時には実行されません。
this.scene.start('X')を呼び出しても、X が同期的に開始されるわけではありません。これは次の SceneManager の更新時に行われます。同じフレーム内でターゲットシーンの状態に依存しないでください。 -
start()は呼び出し元のシーンをシャットダウンします。this.scene.start('X')は現在のシーンを停止し、X を開始します。両方を実行させたい場合は、launch()またはrun()を使用してください。 -
switch()はスリープさせ、start()はシャットダウンします。switch()は現在のシーンをメモリ内に保持し(スリープ)、start()は完全なシャットダウンを引き起こします。スリープ中のシーンでも、そのイベントと参照は生きたままです。 -
一時停止したシーンも依然としてレンダリングされます。
pause()は更新ループを停止するだけです。シーンは依然として描画されます。更新とレンダリングの両方を停止するにはsleep()を使用してください。 -
this.sysを上書きしないでください。 Scene クラスの JSDoc は明示的に警告しています。this.sysを上書きするとすべてが壊れます。 -
キーを指定せずに
this.scene.start()を呼び出すと、現在のシーンが再起動されます。 これはthis.scene.restart()と同等です。 -
start()/launch()に渡されたデータは、init(data)とcreate(data)の両方で利用できます。 これはsettings.dataに保存され、後でthis.sys.getData()を介してアクセスできます。 -
スリープ中のシーンも他のシーンからイベントを受信できます。 シーン A がスリープ中でも、シーン B がグローバルレジストリでイベントを発行すると、シーン A のリスナーは依然として発火します。スリープ中のシーンにあるアクティブなリスナーには注意してください。
-
シーンのレンダリング順序 = 配列の順序です。 配列内で後にあるシーンほど上にレンダリングされます。レイヤリングを制御するには
bringToTop()、sendToBack()、moveAbove()、moveBelow()を使用してください。 -
shutdownとdestroyの違い。 シャットダウンはシーンを休止状態にします(再起動可能)。destroy はシーンを完全に削除します。再起動時に再作成すべきリソースを解放するには'shutdown'をリッスンしてください。最終的なクリーンアップには'destroy'をリッスンしてください。 -
this.physicsやthis.matterのようなプラグインプロパティは、物理システムが構成されている場合にのみ利用できます。 それ以外の場合は undefined になります。 -
createイベントは、create()メソッドが戻った後、ステータスが RUNNING に変わった後に発火します。 create 後のセットアップを行う必要がある場合は、このイベントをリッスンしてください。 -
状態のリセットはコンストラクターではなく
init()で行ってください。 コンストラクターはシーンが最初にインスタンス化されたときに一度だけ実行されます。init()はシーンが開始/再起動されるたびに実行されます。状態のリセットはそこに配置してください。 -
古い参照を避けるために
shutdownでクリーンアップしてください。 ゲームオブジェクトを保持する配列のクリア、外部イベントリスナーの削除などを行うには、this.events.once('shutdown', ...)をリッスンしてください。破棄されたゲームオブジェクトへの古い参照は、再起動時にエラーを引き起こします。 -
switch()は一時停止したシーンを再起動し、決して再開しません。 再開動作が必要な場合は、代わりにrun()を使用してください。 -
シーンは逆順で更新され、順方向にレンダリングされます。 最上位のシーンは最初に更新され(入力の優先権を取得)、最後にレンダリングされます(上に表示されます)。ゲーム設定のシーン配列でレンダリング順序を設定してください。