マガジン

ブラウザゲームのデバッグ方法:開発者ツールで見るべき3画面

遊びをつくる

執筆にClaudeを使用しています。

壊れたビー玉コースを四枚の記録カードと虫眼鏡を使って調べ、修理する手元
記事のテーマをもとに制作したAI生成イラスト。

ブラウザゲームを作っていて「動かない」「表示がおかしい」「音が出ない」と感じたとき、最初に開くべきツールはブラウザに最初から備わっている開発者ツール(DevTools)です。ChromeならF12キー、またはページ右クリック→「検証」で開けます。 ところが開いてみると、タブが十以上並んでいて何を見ればいいかわかりません。ゲームのデバッグに限っていえば、実用的な場面の大半は「Console」「Sources」「Performance」の3つのパネルで解決できます。この記事では、その3つをゲーム開発の観点から掘り下げ、エラーをどう読み、どこに手を入れるかを具体的に説明します。

この記事の目次
  1. Consoleパネル:エラーと状態を読む起点
  2. Sourcesパネル:止めて確かめるBreakpoint
  3. Performanceパネル:重くなる原因を見つける
  4. 3つのパネルを使う順序
  5. 次の行動

Consoleパネル:エラーと状態を読む起点

Consoleはゲームが動かないときに最初に確認するパネルです。JavaScriptのエラー、警告、そして自分で仕込んだconsole.log()の出力がすべてここに流れます。

エラーメッセージは行番号とファイル名つきで表示されます。たとえばUncaught TypeError: Cannot read properties of undefined (reading 'x')という行が出たなら、「定義されていないオブジェクトのxプロパティを読もうとした」という意味です。右端に表示されているファイル名と行番号をクリックすると、Sourcesパネルが開いて該当行にジャンプします。

Consoleを使いこなす上で意識したいのは、ゲームループ内でconsole.log()を呼ばないという鉄則です。60fpsで動くゲームでは毎秒60回呼ばれ、Consoleが一瞬で埋まって他のエラーが流れてしまいます。状態を確認したいなら、条件分岐で「特定フレームだけ出力」するか、後述のBreakpointを使う方が実用的です。

よく見るエラーの種類と対処の方向

  • ReferenceError: XXX is not defined:変数や関数の名前を間違えているか、スコープ外で参照しています。スペルミスとスコープ(let/const/varの宣言位置)を確認します。
  • TypeError: XXX is not a function:関数だと思っていたものが関数でない状態にあります。初期化の順序やオブジェクトの中身を疑います。
  • Failed to load resource: net::ERR_FILE_NOT_FOUND:画像・音声・JSONのパスが間違っています。大文字・小文字の違い、相対パスと絶対パスの混在が原因であることが多いです。

Consoleの左上にある「フィルター」アイコンで「Errors」だけに絞ると、警告の洪水に埋もれずに済みます。まず赤いエラーをすべて潰してから、黄色の警告を見る順番が効率的です。

Sourcesパネル:止めて確かめるBreakpoint

「エラーは出ていないのに挙動がおかしい」というケースで使うのがSourcesパネルです。ここでBreakpoint(ブレークポイント)を設定すると、JavaScriptの実行を任意の行で一時停止し、そのときの変数の中身を確認できます。

操作の手順は次のとおりです。

  1. SourcesパネルでJSファイルを開く(左の「Page」ツリーから選ぶ)。
  2. 止めたい行番号の数字をクリックする。青いマーカーが付いてBreakpointが設定されます。
  3. ゲームを操作してその行に処理が到達すると、実行が止まります。
  4. 右側の「Scope」ペインで、そのタイミングでの変数の値を確認します。
  5. ▶ボタン(Resume)で次のBreakpointまで進みます。F10で1行ずつ進めることもできます。

ゲーム開発でとくに役立つ場面は、衝突判定が期待通り動かないときです。if (checkCollision(player, enemy))という行にBreakpointを置いて止め、Scopeでplayer.xやenemy.widthの値を見ると、座標やサイズが想定と違う値になっているのをその場で確認できます。

条件付きBreakpointで特定の状況だけ止める

行番号を右クリックすると「Add conditional breakpoint」を選べます。ここにplayer.hp <= 0のような条件式を書くと、その条件が真のときだけ止まります。「特定のスコアになったときだけバグが出る」など、再現条件が絞れているときに重宝します。

ゲームループは高速で繰り返されるため、無条件のBreakpointをループ内に置くと止めるたびにResumeを押す羽目になります。条件付きにするか、ループの外側のイベントハンドラーに置くのが現実的です。

Performanceパネル:重くなる原因を見つける

ゲームの動きがカクつく、フレームレートが落ちるという問題は、ConsoleやSourcesでは見えません。このときはPerformanceパネルを使って処理の時間を計測します。

基本的な使い方は、Performanceパネルを開いて「Record」ボタン(丸いアイコン)を押し、数秒ゲームを動かしてからStopします。すると処理の時間をフレームごとに可視化した「フレームチャート」が表示されます。

読み方のポイント

上部のフレームバー:緑のバーが1フレームの処理時間を示します。バーが極端に高くなっている(赤くなっている)場所が、処理が重くなっている瞬間です。

Mainトラック:JavaScriptの各関数がどれだけ時間を使っているかをブロックで表示します。幅が広いブロックほど時間を消費しています。ブロックをクリックすると「どのファイルの何行目の関数か」が下部に表示されます。

Frames行:フレームレートの推移を確認できます。60fpsを安定して出したいなら、1フレームの処理を16ms以内に収める必要があります。

ゲームでよく起きる重さの原因は3種類です。第一に不要なオブジェクトの生成で、ゲームループの中で毎フレームnewで配列やオブジェクトを作り続けると、ガベージコレクション(使われなくなったメモリを回収する処理)が頻繁に走ります。フレームチャートで「GC」という黄色いブロックが規則的に現れるなら、オブジェクトの使い回し(プーリング)を検討します。第二に複雑すぎる描画処理で、毎フレーム多数の画像を重ねて描いている場合はオフスクリーンキャンバスへの事前描画が有効です。第三に重いDOM操作で、Canvas以外にHTMLの要素を毎フレーム書き換えていると、レイアウトの再計算が起きて遅くなります。

3つのパネルを使う順序

バグの性質によって、どのパネルから入るかは決まっています。

  • エラーが出て止まる・動かない、最初に開くパネル:Console
  • エラーはないが挙動がおかしい、最初に開くパネル:Sources(Breakpoint)
  • 動くがカクつく・重い、最初に開くパネル:Performance

迷ったらまずConsoleを開いて赤いエラーがないか確認し、エラーがなければSourcesでBreakpointを使う、という順番が実際の作業に即しています。Performanceは他の2つで解決しなかったときの最終確認として使うのが効率的です。

開発者ツールはどのデバイスで開いているかによって表示が変わることがあります。スマートフォン向けの表示確認はToggle Device Toolbar(Ctrl+Shift+M)を使い、タッチイベントのデバッグもConsoleで同様に行えます。

次の行動

ゲームが「動かない」「重い」という局面になったら、まずF12で開発者ツールを開き、Consoleの赤いエラーを1件ずつ潰すところから始めてください。エラーが消えたら動作確認し、それでも挙動がおかしければSourcesのBreakpointで変数の値を止めて確かめます。デバッグの手順が身についたら、アソバースにZIPファイルで投稿し、実際のブラウザ環境での動作を確認してみてください。