【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

UnityのProject Settings、PlayerのPublishing Settings。Compression FormatがBrotli、Decompression FallbackがON、Enable ExceptionsがExplicitly Thrown Exceptions Only、Initial Memory Size 512MB、Memory Growth Mode Geometric、Maximum Memory Size 2048MBに設定されている

このパネルの一番上、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 圧縮 オン UnityのInspectorで表示したノーマルマップのImport Settings。Defaultタブで Max Size 1024、Compression Normal Quality、Use Crunch Compression チェック済み、Compressor Quality 60 に設定されている

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

UnityのProject Settings、PlayerのOther Settings内にあるOptimizationセクション。Strip Engine Codeがチェック済み、Managed Stripping LevelがHighに設定されている

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 直下

UnityのProjectウィンドウ。Assets直下のフォルダ一覧で、赤枠のResourcesとStreamingAssetsが並んでいる

どちらも名前が決まっている特別なフォルダで、Assets/ の直下に置かれます。無ければそのプロジェクトには存在しないので、気にする必要はありません。

メッシュ設定

確認場所:FBXなどのモデルを選んで Inspector → Model タブ

UnityのInspectorで表示したFBXのImport Settings。Modelタブが開かれ、赤枠のMesh CompressionとRead/Write、および上部タブの赤枠Animationが見えている

  • Mesh Compression: Medium 〜 High(頂点データを量子化して縮める。既定は Off)
  • Read/Write: OFF(ONだとCPU側にもコピーを持つため、メモリが倍になる)
  • 使っていないアニメーションクリップをインポートしない(上部の Animation タブで除外)

使っていないパッケージの除外

Package Managerに残っている未使用パッケージを削除します。

確認場所:メニューバーの Window → Package Manager → 左のリストで「In Project」を選ぶ

UnityのPackage Managerウィンドウ。左のリストで赤枠のIn Projectが選択され、右側にこのプロジェクトが持つパッケージ(Asset Store・Unity製など)が一覧表示されている

ここに出ているのが、このプロジェクトが実際に抱えているパッケージです。使っていないものを選び、右下の Remove で削除します。

以下はプロジェクト作成時に自動で入りがちなので、心当たりがなければ外して構いません。

  • Unity Analytics
  • Advertisement
  • In-App Purchasing
  • Visual Scripting
  • Input System(旧Input Managerしか使っていない場合)

判断に迷ったら、消してビルドが通るかで確かめます。実際に使っていればコンパイルエラーになるので、その場合は Package Manager から入れ直せば元に戻せます。

例外処理のレベルを下げる

実行時に例外を検出するためのコードを、どこまでwasmに埋め込むかの設定です。レベルが高いほど原因は追いやすくなりますが、そのぶんwasmが太ります。

変更箇所:Player Settings → Publishing Settings →「WebAssembly Language Features」の Enable Exceptions

UnityのProject SettingsのPublishing Settings内、WebAssembly Language Featuresセクション。赤枠で囲んだEnable ExceptionsがExplicitly Thrown Exceptions Onlyに設定されている

手順①で開いたパネルの下のほう、Power Preference の次にあります。

ドロップダウンを開くと4段階から選べます。PoseMirrorは上から2番目の Explicitly Thrown Exceptions Only です。

UnityのEnable Exceptionsのドロップダウンを開いた状態。None、Explicitly Thrown Exceptions Only(チェック済み)、Full Without Stacktrace、Full With Stacktraceの4つが並んでいる

選択肢 内容
None 例外処理を一切入れない。最小だが、例外が出た時点で挙動が不定になる
Explicitly Thrown Exceptions Only throw した例外だけ拾う(推奨)
Full Without Stacktrace ぬるぽ等のランタイム例外も拾う。スタックトレースは無し
Full With Stacktrace 上に加えて行番号テーブルをwasmへ埋め込む。いちばん重い

Full With Stacktrace は原因究明には便利ですが、公開ビルドで背負うには重すぎます。開発中だけ上げて、公開前に戻すのが基本です。

手順④:体感時間を縮める

転送量を削り切ったあとに残るのは体感時間の削減です。

進捗バーはUnityの外(HTML)に置く

Unityを埋め込むHTMLに進捗バーを実装します。

PoseMirrorの読み込み中の画面。黒い背景に青い進捗バーが3割ほど伸び、その下にLoading... 30%と表示されている

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アプリとして公開するためには軽量化は避けては通れません。 この記事が参考になれば幸いです。

PoseMirror

この記事の軽量化を入れたUnity WebGLアプリを、以下のリンクから確認できます。

▶ ブラウザで3Dポーズツールを開く

関連記事:

参考資料

← Kabe-Tech トップへ