【Unity】Webアプリで表示するための軽量化方法
投稿日: 2026年5月5日(2026年9月25日更新)
対象読者: Unity WebGLビルドをWebアプリとして公開したい・読み込みを速くしたいエンジニア
はじめに
Unityで作ったプロジェクトはWebGLでビルドすればWebアプリとして動きます。 しかしながら、3Dで動くプロジェクトは重いため、読み込みが遅いなどユーザー体験が悪化するだけでなく、環境によっては読み込みに失敗することもあります。
この記事は、Unityで作ったプロジェクトを組み込んでいる PoseMirror で軽量化のために実際に行っていることを共有していきます。
動作環境
| 項目 | 値 |
|---|---|
| Unity | 6000.0.58f2 |
| レンダーパイプライン | URP |
| Scripting Backend | IL2CPP(WebGLでは固定) |
| ホスティング | Firebase Hosting |
WebGLでビルドしたときの構成物
前提として、Unity WebGLのビルドしたとき Build/ 配下に以下の4ファイルができます。
表1:圧縮なし(Compression Format: Disabled)でビルドしたときの内訳 — サイズはPoseMirrorの値
| ファイル | サイズ | 占める割合 |
|---|---|---|
poseMirror.wasm |
35.88MB | 70.6% |
poseMirror.data |
14.37MB | 28.3% |
poseMirror.framework.js |
0.42MB | 0.8% |
poseMirror.loader.js |
0.11MB | 0.2% |
| 合計 | 50.79MB | — |
wasm と data が全体の99% あり、この2ファイルの容量を減らしていくことが鍵になります。
- wasm(35.88MB)= C#のコードをIL2CPPがC++に変換してコンパイルしたもの
- data(14.37MB)= シーンに含まれるアセット(テクスチャ・メッシュ・アニメーション)
この50.79MBを、以降の3手順で 14.20MB まで落としていきます。
※比較対象の数値は Build/ 配下4ファイルの合計転送量(Brotli圧縮後のバイト数)とします。
手順①:Compression Format を Brotli にする(-72.0%)
ビルド成果物を圧縮形式で書き出す設定であり、影響度がもっとも高い項目となります。
変更箇所:Player Settings → Publishing Settings → Compression Format
このパネルの一番上、Compression Format を Disabled から Brotli に変えます。
Tips:Brotli とは
Google が作った汎用の圧縮形式で、主要ブラウザが展開に標準対応しています。Unity WebGL では Disabled / Gzip / Brotli の3択で、同じ内容なら一般に Gzip より小さくなります。
デメリットとして圧縮にかかる時間が長く、そのぶんビルドが長くなります。開発中は Gzip か Disabled、公開ビルドだけ Brotli という使い分けを推奨します。
なお、圧縮したファイルを配信するには、サーバ側で「圧縮済みである」と伝えるヘッダ設定が別途必要です(公開手順の記事で扱います)。
| ファイル | 圧縮なし | Brotli | 削減 |
|---|---|---|---|
| wasm | 35.88MB | 6.65MB | -81.5% |
| data | 14.37MB | 7.36MB | -48.8% |
| framework.js | 0.42MB | 0.07MB | -83.3% |
| loader.js | 0.11MB | 0.11MB(非圧縮のまま) | — |
| 合計 | 50.79MB | 14.20MB | -72.0% |
容量:50.79MB → 14.20MB(-72.0%)となりました。
手順②:テクスチャを Max Size 1024 + Crunch 圧縮にする(-19.7%)
画像の解像度上限を下げ、さらにGPU用フォーマットの上から圧縮をかける設定です。 data ファイルの容量を削ることができます。
変更箇所:
テクスチャを選んで Inspector → Default タブ → Max Size 1024、Crunch 圧縮 オン

Tips:Crunch 圧縮とは
テクスチャはビルド時にDXTなどのGPU用フォーマットへ変換されます。Crunch(crunch / crnlib)は、その上からさらにかける非可逆の追加圧縮です。配布されるファイルにはCrunchのまま入っていて、読み込み時にCPUがGPU用フォーマットへ戻します。
デメリットは非可逆ゆえの画質低下と、ビルド時間・読み込み時のCPU処理の増加です。法線マップや滑らかなグラデーションではノイズが出やすいので、画質を落とす設定だと理解したうえで、実際の画面で見比べてから適切な設定値を決めることをお勧めします。
| 2048・Crunch OFF | 1024・Crunch ON | 削減 | |
|---|---|---|---|
| data | 10.85MB | 7.36MB | -32.1% |
| 合計 | 17.68MB | 14.20MB | -19.7% |
容量:17.68MB → 14.20MB(-19.7%)となりました
PoseMirrorのような人物モデルを画面に1体だけ表示するような用途なら、1024で見た目の差はほぼありません。2048のまま公開していないか確認してみてください。
手順③:Managed Stripping Level を High にする(-5.8%)
使っていないC#コードとエンジン機能を、ビルド時に切り落とす設定です。 コードを書き換えずに wasm を削ります。
変更箇所:Player Settings → Other Settings → Optimization
Managed Stripping Level を Low から High へ。すぐ上の Strip Engine Code も ON にします。
容量:15.07MB → 14.20MB(-5.8%)
| Low | High | 削減 | |
|---|---|---|---|
| wasm | 7.24MB | 6.65MB | -8.2% |
| data | 7.64MB | 7.36MB | -3.6% |
| 合計 | 15.07MB | 14.20MB | -5.8% |
展開後のwasmで見ると 40.49MB → 35.88MB(-11.4%)です。
その他の軽量化ポイント
ここまでの3手順ほどの効果はありませんが、入れておくと効くものをまとめます。
Resources、StreamingAssets内に余計なファイルを入れない
Resources/ 配下は参照の有無にかかわらず全部入ります。また、StreamingAssets/ は無圧縮で丸ごとコピーされるため余計なファイルは入れないでおきましょう。
確認場所:Project ウィンドウの Assets 直下
どちらも名前が決まっている特別なフォルダで、Assets/ の直下に置かれます。無ければそのプロジェクトには存在しないので、気にする必要はありません。
メッシュ設定
確認場所:FBXなどのモデルを選んで Inspector → Model タブ
- Mesh Compression: Medium 〜 High(頂点データを量子化して縮める。既定は Off)
- Read/Write: OFF(ONだとCPU側にもコピーを持つため、メモリが倍になる)
- 使っていないアニメーションクリップをインポートしない(上部の Animation タブで除外)
使っていないパッケージの除外
Package Managerに残っている未使用パッケージを削除します。
確認場所:メニューバーの Window → Package Manager → 左のリストで「In Project」を選ぶ
ここに出ているのが、このプロジェクトが実際に抱えているパッケージです。使っていないものを選び、右下の Remove で削除します。
以下はプロジェクト作成時に自動で入りがちなので、心当たりがなければ外して構いません。
Unity AnalyticsAdvertisementIn-App PurchasingVisual ScriptingInput System(旧Input Managerしか使っていない場合)
判断に迷ったら、消してビルドが通るかで確かめます。実際に使っていればコンパイルエラーになるので、その場合は Package Manager から入れ直せば元に戻せます。
例外処理のレベルを下げる
実行時に例外を検出するためのコードを、どこまでwasmに埋め込むかの設定です。レベルが高いほど原因は追いやすくなりますが、そのぶんwasmが太ります。
変更箇所:Player Settings → Publishing Settings →「WebAssembly Language Features」の Enable Exceptions
手順①で開いたパネルの下のほう、Power Preference の次にあります。
ドロップダウンを開くと4段階から選べます。PoseMirrorは上から2番目の Explicitly Thrown Exceptions Only です。
| 選択肢 | 内容 |
|---|---|
| None | 例外処理を一切入れない。最小だが、例外が出た時点で挙動が不定になる |
| Explicitly Thrown Exceptions Only | throw した例外だけ拾う(推奨) |
| Full Without Stacktrace | ぬるぽ等のランタイム例外も拾う。スタックトレースは無し |
| Full With Stacktrace | 上に加えて行番号テーブルをwasmへ埋め込む。いちばん重い |
Full With Stacktrace は原因究明には便利ですが、公開ビルドで背負うには重すぎます。開発中だけ上げて、公開前に戻すのが基本です。
手順④:体感時間を縮める
転送量を削り切ったあとに残るのは体感時間の削減です。
進捗バーはUnityの外(HTML)に置く
Unityを埋め込むHTMLに進捗バーを実装します。
Unityのcanvasは起動するまで真っ黒のままなので、この帯が無いと「壊れて止まっている」ように見えます。
createUnityInstance の第3引数が進捗コールバックです。Unityが起動しきるまでは画面に何も出ないので、HTML側のオーバーレイで進捗を見せます。
const overlay = document.getElementById('unity-loading-overlay');
const bar = document.getElementById('loading-bar');
const loadingText = document.getElementById('loading-text');
createUnityInstance(unityCanvas, config, (progress) => {
const pct = Math.round(progress * 100);
bar.style.width = pct + '%';
loadingText.textContent = `Loading... ${pct}%`;
}).then((instance) => {
overlay.style.opacity = '0';
setTimeout(() => { overlay.style.display = 'none'; }, 500);
}).catch((err) => {
// 失敗時に白画面のまま放置しない。ここが無いとユーザーは固まったと判断する
loadingText.textContent = '読み込みに失敗しました。ページを再読み込みしてください。';
loadingText.style.color = '#d9534f';
console.error('Unity load error:', err);
});
最後に
いかがでしょうか。Webアプリとして公開するためには軽量化は避けては通れません。 この記事が参考になれば幸いです。
関連記事:
- 【Firebase】Unity WebGLを無料で公開する手順:デプロイ手順の詳細
- 【Unity】WebGLでピンチズームが効かない原因と解決法:スマホのタッチ操作まわり
- PoseMirrorのパフォーマンス改善メモ:起動後のフレームレート改善







