公開すると画像が消える理由:ゲーム素材のパスとファイル名を見直す
遊びをつくる執筆にClaudeを使用しています。

ゲームをZIPにまとめてアップロードした直後、タイトル画面のロゴが消え、効果音も鳴らなくなった——そんな経験はないでしょうか。ブラウザーの開発者ツールを開くと、コンソールには「404 Not Found」やリソース読み込みエラーが並んでいる。コードには触っていないのに、なぜ。原因はほぼ三つのどれかに収まります。この記事では、絶対パス・ファイル名の大文字小文字・ZIPの内部構造を順に取り上げ、それぞれの失敗例と修正後の書き方を具体的に示します。本記事はClaudeが執筆し、アソバース編集部が編集・確認しています。人間による取材やプレイテストは行っていません。
この記事の目次
ローカルで動いてもサーバーで動かない理由
自分のパソコンでゲームを開くとき、ブラウザーはハードディスク上のファイルを直接読みにいきます。このとき参照しているのは「ファイルシステム」であり、URLスキームとしては file:// が使われています。アップロード後に他の人がアクセスするときは、ウェブサーバーが https:// 経由でファイルを配信します。この二つの環境は、ファイルを探す起点も、大文字小文字の扱いも、まったく異なります。
WindowsとmacOSのファイルシステムは、デフォルトで大文字小文字を区別しません。Image.png と書いても image.png と書いても、同じファイルを見つけてくれます。一方、多くのウェブサーバーが採用しているLinuxのファイルシステムは大文字小文字を厳密に区別します。ローカルで動いていたコードが、アップロードした瞬間に壊れて見える大きな理由のひとつはここにあります。
原因① ローカルの絶対パスがそのまま残っている
最も多い失敗のひとつが、パソコン上のフォルダ構造をそのままパスに書き込んでしまうケースです。たとえば次のような記述です。
// 失敗例:Windowsのローカルパスがそのまま入っている
const img = new Image();
img.src = 'C:/Users/yourname/Documents/mygame/assets/player.png';
// 失敗例:Macのローカルパス
img.src = '/Users/yourname/Desktop/game/assets/player.png';このパスはあなたのパソコンにしか存在しません。公開サーバー上には C:/Users/yourname/ というフォルダはなく、他のプレイヤーのパソコンにも当然ありません。ブラウザーがこのパスを解釈しようとすると、HTTPリクエストとして存在しないURLを要求して404エラーになるか、あるいはセキュリティ上の理由でブラウザー自体がアクセスを拒否して読み込みに失敗することがあります。いずれの場合も素材は表示されません。
修正するには、HTMLファイルを起点にした相対パスを使います。ゲームのHTMLファイルと同じ階層に assets フォルダがある場合は次のように書きます。
// 修正例:相対パス(HTMLと同じ階層に assets/ フォルダがある場合)
img.src = 'assets/player.png';
// HTMLファイルが一段下の game/ フォルダにある場合
img.src = '../assets/player.png';相対パスはHTMLファイルの場所を起点に解釈されます。JSファイルの場所ではありません。fetch() や XMLHttpRequest などでURLを組み立てる場合も同様です。
原因② ファイル名の大文字小文字が一致していない
ファイルの実名が Player.png(Pが大文字)なのに、コード内では player.png(pが小文字)と書いている——この不一致はローカルでは無視されますが、Linuxサーバーでは別のファイルとして扱われ、見つからなくなります。スペースや全角文字も同様に問題の種になります。
ファイル名を統一する基本方針
- ファイル名はすべて小文字のアルファベット・数字・ハイフン・アンダースコアだけで構成する
- スペース(半角・全角とも)を使わない。スペースが必要な箇所はハイフン - またはアンダースコア _ に置き換える
- 拡張子は小文字に統一する(.PNG ではなく .png)
- コード内のパス文字列と、実際のファイル名・フォルダ名が一字一句一致しているかを確認する
プロジェクトのファイルが多くなってきたら、ローカルでLinuxに近い確認をする方法があります。macOSでは、ターミナルで ls assets/ を実行すると実際のファイル名が確認できます。Windowsでは、WSLやGit Bashで同様に確認できます。ただしこれは手元環境での目視確認であり、サーバー環境と完全に一致することを保証するものではありません。
原因③ ZIPの内部フォルダ構造がコードとずれている
ZIPファイルを作成するとき、フォルダのまとめ方によって内部の階層が変わります。「フォルダを選択してZIPにする」か「フォルダの中身を選択してZIPにする」かで、解凍後の構造がまったく異なります。この違いがコード内のパスとずれると、素材が見つからなくなります。
ZIPの構造パターンと対応するパスの書き方
たとえば、手元に次のようなフォルダ構造があるとします。
mygame/
index.html
assets/
player.png
bgm.mp3このとき、「mygameフォルダそのものをZIPにした」場合と「mygameの中身をZIPにした」場合では、サーバー上での配置が変わります。
- フォルダごとZIPにした場合:ZIP内は mygame/index.html という構造になる。サービスによってはこの場合にエントリポイントを正しく認識できないことがある
- フォルダの中身をZIPにした場合:ZIP内は index.html と assets/ が直下に並ぶ。一般的にこちらが意図した構造
投稿先のサービスがZIPを展開するときに index.html を起点とする場合、index.htmlがZIPの直下に来るように中身だけを選択してZIPを作るのが安全です。フォルダごと圧縮してしまった場合、エントリポイントが一段深くなり、サービスがHTMLを見つけられないことがあります。
Macの「フォルダをダブルクリックして全選択してからZIPにする」操作と、「フォルダを右クリックして圧縮」の操作では内部構造が変わります。後者はフォルダ名がZIP内に1段入ります。投稿前にZIPを解凍して確認する習慣をつけると、この問題は事前に防げます。
投稿前に確認する6項目
以下の項目をZIPを作成する前に一度確認してください。コードを変えていなくても、ファイルを整理したあとに問題が発生することがあります。
- ローカルパスが残っていないか:コード内を C:/ や /Users/ で検索し、一件でも見つかったら相対パスに書き直す
- パスの区切りが正しいか:Windowsのパスは \(バックスラッシュ)を使うが、ウェブのURLは /(スラッシュ)を使う。コード内はスラッシュに統一する
- ファイル名が全部小文字か:ファイル名・フォルダ名・コード内のパス文字列をそれぞれ目視して一致を確認する
- 拡張子が小文字か:.PNG や .MP3 などが混入していないかを確認する
- ファイル名にスペースや特殊文字が含まれていないか:スペースはURLエンコードされ、予期しない参照エラーを起こすことがある
- ZIP展開後にindex.htmlが直下にあるか:いったんZIPを解凍してみて、index.html が最上位に来ていることを目で確かめる
アップロード後にブラウザーで原因を特定する
それでも素材が消えてしまったときは、ブラウザーの開発者ツールを使うと原因を素早く絞り込めます。操作はChrome・Firefox・Edgeで共通して使えます。
- ゲームのページを開き、F12(またはCmd+Option+I)で開発者ツールを開く
- 「コンソール」タブを選ぶ。赤い文字で 404 や Failed to load resource と表示されているエラーが、読み込めなかったファイルのURLを示している
- エラーに含まれるURLを確認し、実際のファイル名・フォルダ名と1文字ずつ照合する
- 「ネットワーク」タブでリクエスト一覧を確認すると、ステータス200(成功)と404(失敗)を一覧で比較できる
エラーに表示されたURLを見ると、ローカルパスが含まれているのか、大文字小文字が違うのか、フォルダ階層がずれているのかが一目でわかります。ブラウザーは「どこを探しに行って、見つからなかったか」をログに残してくれます。修正したらZIPを作り直し、再度投稿してコンソールのエラーが消えるまで確認してから完了とするのが確実です。


