# リスナーごとに所有者と有効期間を一つずつ定める

> 各シーンのイベントリスナーに明確な所有者、登録のタイミング、解除方法を設け、入力やコールバックの重複を防ぎます。

- URL: https://oneshotgems.ai/ja/topics/preventing-game-event-listener-duplicates
- カテゴリ: ゲーム開発者向け
- 種類: ガイド
- 更新日: 2026年10月5日

再起動後に一度のクリックで処理が二回実行されるなら、シーンを開くたびにリスナーを登録し、閉じるときに解除していない可能性があります。この目に見える重複動作は、広範なメモリーリーク調査とは別の問題です。まず登録回数を数え、シーンのライフサイクルに結び付けてください。各リスナーには明確な所有者、その所有者ごとに一度だけ実行する登録処理、そしてシーンが入力を受け付けなくなるときの解除処理が必要です。

## ライフサイクルの適切な境界で登録する

描画関数や毎フレームの処理からwindowのkeydownハンドラーを登録するのは避けてください。シーン固有の初期化は開始時またはマウント時の関数に置き、その関数が後片付けなしで二度実行されないようにします。removeEventListenerを使う場合はコールバックへの参照を保持してください。毎回作り直す無名関数は、後から対応するものを指定して解除するのが困難です。別の方法として、関連するハンドラーをAbortControllerでまとめ、リスナーのオプションにそのsignalを渡し、シーンの終了時にまとめてabortできます。

イベントの対象も慎重に選びます。ゲームがアクティブな間、キー入力に対してwindow全体のリスナーを使うのは適切な場合がありますが、ボタンのclickハンドラーはそのボタンに登録します。イベントの伝播を意図的に利用する設計でない限り、親要素の委譲ハンドラーと直接のハンドラーの両方を同じ操作に登録しないでください。

## シーンへの再入場を症状確認として試す

シーンを開いて操作を一度実行し、シーンを離れてから再び開きます。一度の入力で起きる効果が一つであることを確認してください。このサイクルを5回繰り返し、押すたびに反応が一回だけ起きることを確かめます。これは機能の確認であり、メモリー使用量の測定ではありません。退出後に前のシーンへの入力がそのスコアや状態を変えないことも確認します。MDNは、AbortSignalを使ってリスナーをまとめて管理できることを説明しており、明示的に解除する無名関数については参照を保持する必要があるとしています。

## 所有者に合わせて後片付けする

シーンを切り替えるときは、そのリスナーが参照するオブジェクトを破棄する前に、リスナーをabortするか解除します。アプリ全体のシェルに属するリスナーがある場合は、各ラウンドで解除するのではなく、より長く存続する所有者に持たせます。再起動、一時停止、メニューへの復帰で同じシーンを誤って二重にマウントしたり、後片付けを飛ばしたりしないよう、回帰テストを追加してください。

## よくある質問

**キーを一度押しただけで、ゲーム内の操作が複数回起きるのはなぜですか？** 同じ操作に複数のハンドラーが登録されているか、親要素と子要素の両方がイベントを処理している可能性があります。登録数を数え、シーンのライフサイクル境界でイベントの伝播を確認してください。

**AbortControllerでイベントリスナーを解除できますか？** できます。同じsignalを指定して関連するリスナーを登録し、所有者が終了したときにabortを呼び出します。これでまとめて解除する明確な経路を作れますが、誰がそれらを所有するかを決める必要はあります。

## 気になることを、もっと

- [ブラウザ ゲームのメモリ リークを追跡する](https://oneshotgems.ai/ja/topics/game-memory-leaks): 反復可能なプレイとクリーンアップ チェックを使用して、時間の経過とともに蓄積される保持されたゲーム シーン、リスナー、タイマー、アセットを見つけます。
- [ブラウザ ゲームでのフォーカスの管理](https://oneshotgems.ai/ja/topics/game-focus-management): ゲームに可視のフォーカス状態を与え、オーバーレイが閉じた後にフォーカスを復元することで、キーボード入力、メニュー、リターン パスを予測可能にします。

## 関連情報

- [MDN addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)

---
正規ページ: https://oneshotgems.ai/ja/topics/preventing-game-event-listener-duplicates
