UnityのWebゲームの読み込み時間を測る(軽量化の前後で比較)
ダウンロード 0.76秒、起動 0.6秒、プレイ中 60.1fps。10.1MB 版と 7.37MB 版を同じ条件で比べたら起動が19%速くなりました。計測用ページの作り方と、圧縮を外したあとのサイズという見落としがちな数字、そして fps の計測でつまずいた話です。
公開 2026年9月16日
この記事の要点6 points
- ダウンロードは 7,325,986 バイトで 0.755秒(約78Mbps の回線)。 そこから遊べるようになるまで 0.62秒。
- 軽量化の前後を同じ条件で比べると、起動が 約705ms → 約569ms(−19%)になった。
- 圧縮を外したあとのサイズは wasm が 38.3MB → 23.7MB(−38%)。 ダウンロード量(−23%)より大きく減っている。
- スマホ幅では devicePixelRatio 2 のせいでキャンバスの実解像度が 750×1624 になる。 画素数は2倍かかる。
- プレイが続いている状態の fps は 60.1。 60Hz のディスプレイなので上限に張り付いている。
- fps は自動で測れなかった。 非表示のタブでは requestAnimationFrame が進まないため、画面に見えているタブが要る。
目次7章
検証した環境最終確認 2026年9月16日
- Unity 6.6(6000.6.0f1)・WebGL・Brotli 圧縮
- Windows 11・Chromium 系ブラウザ
- 配信は VPS 上の Caddy(Content-Encoding: br)
- 回線:光(実測 約78Mbps でこのサーバーから取得)
書いてあるのは、この環境で実際に試した結果です。ツールの仕様や料金は変わるので、重要な判断の前には公式の情報も確認してください。
ビルドを 10.1MB から 7.37MB に減らしました。で、実際どれだけ速くなったのか。
サイズの記事に「測れたら追記する」と書いたので、測りました。
結果
0.76秒
ダウンロード
7,325,986 バイト・約78Mbps
0.6秒
遊べるようになるまで
ダウンロード済みから
約1.4秒
初めて開いたとき
上の2つの合計
60.1
プレイ中の fps
60Hz のディスプレイ
- 10.1MB 版約705 ms
- 7.37MB 版約569 ms
ローカルサーバーで4〜6回ずつ測った中央値。回線の影響を外した、展開とコンパイルの時間です。
起動が19%速くなりました。 ダウンロードが27%減った分に加えて、展開とコンパイルの時間も減っています。
ダウンロードの内訳(本番・光回線)
配信は自分の VPS(Caddy が Content-Encoding: br を返す)です。ブラウザのキャッシュを使わずに取り直して測りました。
- wasm.br(5,635,795 バイト)545 ms
- data.br(1,618,640 バイト)190 ms
- framework.js.br(71,551 バイト)20 ms
合計 7,325,986 バイトを 755 ms。ほぼ wasm の時間です。
約78Mbps 出ています。この回線なら 1.4秒で遊び始められる。 ただし、これは速い回線での話です。実際には回線が細いほど、サイズを減らした効果が大きく出ます。
見落としやすい数字:圧縮を外したあとのサイズ
ダウンロード量ばかり見ていましたが、展開後のサイズのほうが大きく減っていました。
- 10.1MB 版:展開後38,332,803
- 7.37MB 版:展開後(−38.3%)23,663,474
- 10.1MB 版:転送量7,333,280
- 7.37MB 版:転送量(−23.1%)5,635,795
ダウンロード量より、展開後のほうが大きく減っている。
| 10.1MB 版 | 7.37MB 版 | 差 | |
|---|---|---|---|
wasm 転送量 | 7,333,280 | 5,635,795 | −23.1% |
wasm 展開後 | 38,332,803 | 23,663,474 | −38.3% |
data 転送量 | 2,689,477 | 1,618,640 | −39.8% |
data 展開後 | 10,373,688 | 6,706,246 | −35.4% |
展開後のサイズはメモリと wasm のコンパイル時間に効きます。14.7MB 分のコードをコンパイルしなくてよくなったということです。起動が19%速くなったのは、ここが効いています。
この数字はブラウザの Resource Timing から取れます。
performance.getEntriesByType('resource').map(r => ({
file: r.name.split('/').pop(),
transferred: r.encodedBodySize, // 転送量(圧縮後)
expanded: r.decodedBodySize, // 展開後
}))
計測用のページを作る
本番のページにはローディング表示や全画面ボタンが載っていて、どこが「遊べるようになった瞬間」なのかが分かりにくい。計測用の小さい HTML をビルドのフォルダに置きました。
<canvas id="c" width="800" height="450"></canvas>
<script>
var t0 = performance.now();
var s = document.createElement("script");
s.src = "Build/WebGL.loader.js";
s.onload = function () {
createUnityInstance(document.getElementById("c"), {
dataUrl: "Build/WebGL.data.br",
frameworkUrl: "Build/WebGL.framework.js.br",
codeUrl: "Build/WebGL.wasm.br",
streamingAssetsUrl: "StreamingAssets",
companyName: "m", productName: "m", productVersion: "1"
}).then(function () {
window.READY = performance.now() - t0; // ここが「遊べるようになった」時刻
});
};
document.body.appendChild(s);
</script>
これをビルドごとに置けば、同じ物差しで比べられます。
スマホ幅で見る(エミュレーション)
実機ではなく、ブラウザの端末エミュレーション(Pixel 8 の UA・375×812・タッチ5点)です。
- 起動する。コンソールにエラーなし
- 縦画面いっぱいにレイアウトされ、HUD とブロックとパドルが全部入る
- タップで開始・発射でき、スコアも入る
ただし1つ気になる数字がありました。
375×812
CSS 上のサイズ
Pixel 8 のエミュレーション
×2
devicePixelRatio
高精細の画面
750×1624
キャンバスの実解像度
約122万画素を描く
描画している画素は 121.8万。スマホの GPU にとっては軽くない量です。Unity の WebGL テンプレートには config.devicePixelRatio = 1; という行(既定ではコメントアウト)があり、これを有効にすると等倍で描いて負荷を落とせます。見た目は少しぼやけます。
実機で fps を測ってから決めることにしました。
fps:60.1(ただし自動では測れなかった)
プレイ中の実測です。
60.1
fps
ボールが動いている状態・10秒平均
603ms
起動まで
同じ計測ページで
60Hz
ディスプレイ
1920×1080・これが上限
環境は Chrome(Windows 11)・GeForce RTX 2080 Ti です。
60 に張り付いています。 ただしこれは「速い」ことの証明にはなりません。ディスプレイが 60Hz なので、上限に当たっているだけです。1フレームにどれだけ余裕が残っているかは、この測り方では出ません。低い性能の端末で測るのが次の手です。
詰まったところ:非表示のタブでは測れない
requestAnimationFrame の呼ばれた回数を10秒数えれば fps が出る。そう思って自動操作のブラウザで走らせたら、10秒で1回しか呼ばれませんでした。
{ n: 1, fps: null, hidden: true }document.hidden が true。画面に映っていないタブでは requestAnimationFrame が進みません。 Unity の描画ループも同じ仕組みなので、そもそも描画されていません。バックグラウンドのタブに切り替えても同じです。
同じ理由で、ページを開いた直後の1回目は低く出ます。 ウィンドウを切り替えている最中のフレームが欠けるためです。10秒ごとに測り直して、2回目以降の値を見てください。
結局、fps だけは人が見ている画面で測りました。 計測用ページに数字を出して、実際に遊んでもらった値が上の 60.1 です。
画面が要る(自動化できない)
自動で回せる
fetch と Resource Timing はタブが見えていなくても動く)まとめ
- ダウンロード 0.76秒+起動 0.62秒=約1.4秒(78Mbps の回線で)
- 軽量化で起動が19%速くなった(705ms → 569ms)
- 展開後のサイズはダウンロード量より大きく減る(wasm −38%)。ここが起動時間に効く
- 計測はタブを毎回開き直す。同じタブだと WebGL のコンテキストが尽きて黙って止まる
- fps は 60.1。ただし 60Hz の上限に当たっているだけで、余裕の量までは分からない
- fps は見えているタブでしか測れない。自動化からは外す
FAQ
よくある質問
読み込み時間はどこからどこまでを測ればいいですか?
ページを開いた瞬間から、操作できるようになるまでです。今回は createUnityInstance が解決した時点にしました。Unity のテンプレートは進捗が1になった時点でローディング表示を消すので、そこを見ても近い値になります。
同じタブで測り直すと値が変になります。
WebGL のコンテキストには数の上限があり、前のインスタンスを終了せずに読み込み直すと新しいインスタンスが作られません。進捗0のまま止まります。計測ごとにタブを開き直すのが確実です。
展開後のサイズは何に効きますか?
メモリと、wasm のコンパイル時間です。ダウンロードが同じでも展開後が小さいほど起動は速くなります。今回はダウンロードが23%減に対して、展開後の wasm は38%減っていました。
スマホでの実測はしましたか?
していません。ブラウザの端末エミュレーション(Pixel 8 の UA・375×812・タッチ5点)で動作とレイアウトは確認しましたが、これは PC の性能で動いています。実機の fps と読み込み時間は別に測る必要があります。
fps はどう測ればいいですか?
requestAnimationFrame の呼ばれた回数を数えるのが簡単です。ただし非表示のタブでは呼ばれません。自動操作のブラウザで測ろうとしたところ、10秒間で1回しか呼ばれませんでした(document.hidden が true)。画面に見えている状態で測ってください。
60.1fps は「余裕がある」という意味ですか?
そこまでは分かりません。ディスプレイが 60Hz なので、上限に当たっているだけです。1フレームにどれだけ余裕があるかは、この測り方では出ません。低い性能の端末で測るか、垂直同期を外して測る必要があります。
この記事は役に立ちましたか?
NEXT
あわせて読む
UnityのWebビルドを10.1MB→7.4MBにした(−27.3%・2段階の実測)
まず設定2つで 10,143,315 → 7,945,839 バイト。次に未使用パッケージ39件を外して 7,374,207 バイト。合計 −27.3% です。効かなかった施策(スプラッシュ停止)も数字ごと残します。
UnityのWebゲームを自前サーバーで公開する(Caddyの設定と実測)
Unity の WebGL ビルドを自分のサーバーで配信するときに必要な設定を実測で残します。.br に Content-Encoding と application/wasm を付ける、末尾スラッシュの 308、前段の圧縮との二重がけ、アップロードと反映にかかった時間。
AIにUnityのテスト・動作確認・ビルドまで回させる手順
Unity CLI の run_tests / editor_play / capture_game_view / build を使って、人が画面を触らずにテストと動作確認とWebGLビルドを回した手順を、実際のコマンドと所要時間つきで残します。