optimize-web について
Unity の Web ビルドのサイズと性能に関わる設定を監査・調整するスキルです。基準値と復元ポイントを作成し、Unity CLI と Editor を使った文書に基づく変更と検証を案内します。
主な機能
- 01Web ビルド設定の監査
- 02基準値と復元ポイントの作成
- 03圧縮とコードストリッピングのガイド
- 04Unity CLI による Editor 設定
- 05ビルドと実行時の検証手順
活用シーン
- 01Unity Web ビルドのサイズ削減
- 02圧縮とストリッピング設定の確認
- 03根拠資料に基づく Web Player 設定の適用
- 04変更前後のビルド設定の比較
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ unity-technologies/ skills --skill optimize-webインストール後、Claude Code で/optimize-webを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
SECURITY.mdscripts/toktx-examples.shWebOptimizer.cs詳細
Unity Web ビルドを小型化・高速化するために、Player Settings、圧縮、ストリッピング、サーバー設定を監査して適用します。
重要
- 各手順で unity cli(
unity command --format json)とunity-cliスキルを使用してください。利用可能な場合はunity-pipelineも使用してください。 - 変更を加える前に、現在の動作のベースラインを確認し、後で結果が実際に変更によるものか判断できるようにしてください。
- 変更が失敗した場合にロールバックできる復元ポイントを作成してください。
- 指示された作業だけを行ってください。無関係なアセットやファイルは変更しないでください。
- 変更が実行時の動作に影響する場合は、実際のシーンの動作を証明できる
Debug.Log行を追加してください(変更内容だけを示すものではありません)。後で検証するため、Play モードに入ったときにこれらのログを確認します。たとえば、修正によって GameObject のサイズが変わるようにする場合は、その Transform のスケールをログに出してください。 - 長い説明は避けてください。
パフォーマンスに関する注意
- 時間をかけて、作業を徹底してください。
- 速度より品質を重視してください。
トピック全一覧
ワークフローや診断を進める前に:
- 実行または修正しようとしている内容に関連する特定のトピックを扱うドキュメントページを開いて読み、見落としがないか確認してください。
- 回答の中で、読んだファイル名を明記してください。
Unity に関するトレーニング済みの知識は、古くなっていたり、誤っていたり、異なる Unity バージョン向けだったりする可能性があるためです。
Editor のインストールフォルダーに Data/Documentation フォルダー(例:...Unity/Hub/Editor/6000.6.0b2/Editor/Data/Documentation)がある場合は、<editor-install>/Editor/Data/Documentation/en/Manual フォルダーから html ファイルを読んでください。それ以外の場合、ドキュメントページはオンラインの https://docs.unity.com/en-us/engine/<VERSION>/manual/ にあります。
このスキルが使用するパッケージ(com.unity.cloud.ktx、com.unity.addressables、com.unity.web.stripping-tool)については、ドキュメントページは Unity Manual をローカルで Markdown に変換したもので、<project-folder>/Library/PackageCache/<package-name>@*/ に保存されています。その特定の PackageCache サブフォルダー内の .md ファイルだけを読んでください。.md ファイルがない場合は、代わりに https://docs.unity3d.com/Packages/<package-name>@<VERSION>/manual/ を使用してください。
WebSearch よりも WebFetch を優先してください。より高速で、目的のリファレンスに直接アクセスできます。必要なページだけを取得してください。取得する前に、<VERSION> を以下の値に置き換えてください。
- docs.unity3d.com:Unity のバージョン。例:
6000.6 - docs.unity3d.com のパッケージ:パッケージのバージョン。例:
@6.6または@2.0。不明な場合は、パッケージのバージョンを確認してください。 - docs.unity.com:Unity のバージョン。例:
6000.6
ProjectSettings/ProjectVersion.txt から Unity のメジャー・マイナーバージョンを読み取ってください(例:6000.0.58f1 から 6000.0。ビルド番号全体では 404 になります)。また、Packages/packages-lock.json から各パッケージのメジャー・マイナーバージョンを読み取ってください。
- Web ビルドを最適化するための推奨 Player 設定 — ローカルの
web-optimization-player.html:圧縮、ストリッピング、例外、メモリのリリース向けの値。 - C# コードを使用して最適化設定を有効にする — ローカルの
web-optimization-c-sharp.html:推奨設定を一度に適用するエディタースクリプト。 - Web ビルドから未使用のリソースを削除する — ローカルの
web-optimization-remove-resources.html:未使用パッケージの削除とシェーダーバリアントのストリッピング。 - 配布サイズとコードストリッピング — ローカルの
webgl-distributionsize-codestripping.html:Web ビルドのサイズを左右する要因とストリッピングの仕組み。 - Web アプリケーションをデプロイする — ローカルの
webgl-deploying.html:サーバーの圧縮ヘッダー、MIME タイプ、Decompression Fallback。 - Unity Web のメモリ — ローカルの
webgl-memory.html:Wasm ヒープサイズ、メモリの拡張、ブラウザーのメモリ制限。
API リファレンス
API は UnityEditor.PlayerSettings、UnityEditor.PlayerSettings.WebGL、UnityEditor.WebGL.UserBuildSettings で、Unity Engine の一部です。Unity のバージョンごとに異なるため、特定のクラスやメソッドを使用する前に、プロジェクトの Unity バージョンを確認してください。
unity-cliスキルを使用して、プロジェクトの Unity バージョンを確認します。- Editor のインストールフォルダーに
Data/Documentationフォルダーがある場合(例:.../Unity/Hub/Editor/6000.6.0b2/Editor/Data/Documentation)、その中のen/ScriptReferenceフォルダーにある html ファイルを grep し、残りの手順はスキップします。 - それ以外の場合は、
https://docs.unity3d.com/<VERSION>/Documentation/ScriptReference/xrefmap.ymlを取得してキャッシュします(<VERSION>を Unity のバージョンに置き換えます。例:6000.3)。このファイルには、各公開 API メンバーの完全修飾名がuidとして記載されています(例:uid: 'UnityEngine.Rigidbody.AddForce(UnityEngine.Vector3)')。 - クラスやメソッドを検索するたびにファイルを再取得するのではなく、yml ファイルをローカルで grep します。ファイルは大きく(約 6 MB)、全体を読み込まないでください。
uidを Markdown ページに変換します。括弧内のパラメーターを削除し、小文字に変換して、.を/に置き換え、.mdを追加します。その後、https://docs.unity.com/en-us/engine/<VERSION>/script-reference/<converted uid>を取得します。たとえば、UnityEngine.Rigidbody.AddForce(UnityEngine.Vector3)はhttps://docs.unity.com/en-us/engine/6000.3/script-reference/unityengine/rigidbody/addforce.mdになります。すべてのオーバーロードは同じページにあります。- コンストラクターには
ctorを使用します(例:unityengine/vector3/ctor.md)。インデクサーにはitemを使用します(例:unityengine/vector3/item.md)。 - ページ内のリンクは
/engine/で始まります。先頭にhttps://docs.unity.com/en-usを追加してください。 - その Unity バージョンのページが存在しない場合は、代わりに
xrefmap.ymlの該当エントリーにあるhrefを使用します(例:href: 'Rigidbody.AddForce.html'=>https://docs.unity3d.com/6000.3/Documentation/ScriptReference/Rigidbody.AddForce.html)。
- コンストラクターには
API はバージョン間で頻繁に非推奨になるため、学習時の知識に頼らず、必ずプロジェクトの Unity バージョンのドキュメントを使用してください。
KTX API(KtxUnity)は com.unity.cloud.ktx パッケージの一部です。Unity のバージョンではなくパッケージのバージョンごとに異なるため、特定のクラスやメソッドを使用する前に、プロジェクトにインストールされているパッケージのバージョンを確認してください。
Packages/packages-lock.jsonから、インストールされているパッケージのバージョンを読み取ります。https://docs.unity3d.com/Packages/com.unity.cloud.ktx@<version>/xrefmap.ymlを取得してキャッシュします(<version>をインストールされているパッケージのバージョンに置き換えます。例:3.4)。このファイルには、各公開 API メンバーの完全修飾名と、そのドキュメントページのhrefが対応付けられています。- クラスやメソッドを検索するたびにファイルを再取得するのではなく、yml ファイルをローカルで grep します。ファイル全体を読み込まないでください。
手順
- プロジェクトのコンテキストを確認します。
ProjectSettings/ProjectVersion.txtから Unity のバージョンを、Packages/packages-lock.jsonから必要なパッケージ(com.unity.cloud.ktx、com.unity.addressables、com.unity.web.stripping-tool)のバージョンを取得します。プロジェクトがない場合は、Unity6000.0を想定します。packages-lock.jsonに記載のないパッケージについては、そのパッケージのドキュメントにある最新バージョンを想定します。確認できたバージョンはすべて保持し、実際に不足している値だけをデフォルトにします。レポートには各想定を明記して、作業を続けます。ユーザーが最適化したい内容を指定しておらず、参照できるプロジェクトもない場合は、何を改善したいかを尋ねます。 - Full topic map から、タスクに関するドキュメントページを読みます。
- Running C# in the Editor の説明に従って
evalを設定します。アクセス可能な Editor がない場合、またはevalが見つからない場合は、その旨を伝えて手順 5 に進み、その後は手順 9 に進みます。レポートでは、ビルドの検証とランタイムチェックを未実施として記載し、手順 2 のユーザーの要望とドキュメントに基づいて推奨事項を提示します。 - 0. Pre-Flight と 1. Assess Current State を実行します。その結果をベースラインとします。
- 要望に合致する行を 2. Understand Request から選びます。
- 復元ポイントを作成してから、3. Web Build Optimization Workflow の変更を適用します。症状が 5. Troubleshooting に該当する場合は、その項目に従います。
- 4. Validation を実行します。[Pre-Flight] のスニペットを再実行し、値をベースラインと比較します。
- Final step のチェックを実行します。
- Final report を提出します。
Running C# in the Editor
Player Setting を読み書きする以下の各手順は、Unity CLI を通じて実行中の Editor 内で行います。Editor への接続は unity-cli スキルが担当します。CLI のインストール、接続済み Editor の確認、プロジェクトへの com.unity.pipeline パッケージの追加、Editor が本当に存在しない場合と Safe Mode で停止している場合の見分け、Editor のコマンドカタログの確認は、このスキルに従ってください。まずスキルの手順を実行し、ここで同じことを改めて調べないでください。
このスキルでは把握できない点が 2 つあります。
- アクセス可能な Editor だけではなく、特に
evalが必要です。 カタログにevalが表示されることを確認してください。利用できるかどうかは CLI ではなく Pipeline パッケージのバージョンによって決まるため、インストールが正常でもevalがない場合があります。見つからない場合はその旨を伝え、設定を読み書きする手順を省略してください。 - 必要に応じて
ProjectSettings/ProjectSettings.assetから Player Settings を読み取ることはできますが、その方法で書き込まないでください。 シリアライズされた名前は API の名前と一致しません。また、これらの設定のいくつかはビルドターゲットごとに異なり、手動で編集した値はビルドで実際に使用される値と食い違っても検出されません。Editor に接続できない場合は、書き込み手順を中止してください。
unity command eval --code '<snippet>' で C# を実行します。unity command のデフォルトのタイムアウトは 30 秒です。
eval への C# の渡し方
eval がコンパイルするのはファイルではなくステートメントブロックなので、using ディレクティブを使わず、完全修飾型名を使用してコードを記述してください。コードがコンパイルできない場合は、以下でエラーを確認してください。
| エラー | 原因 | 修正方法 |
|---|---|---|
CS0210 | using UnityEditor; のような using ディレクティブを、コンパイラーがリソース破棄ステートメントとして読み取っている | ディレクティブを削除し、型を修飾する |
CS0246 | PlayerSettings のような非修飾型 | UnityEditor.PlayerSettings のように完全修飾名を使用する |
CS0104 | Object が object と曖昧になっている | UnityEngine.Object を使用する |
このスキルが監査する設定の読み取り
1 回の呼び出しで、プリフライトの全体像を取得できます。Unity 6000.5.7f1 で検証済みです。
var target = UnityEditor.Build.NamedBuildTarget.WebGL;
var w = new System.Collections.Generic.List<string>();
w.Add($"activeBuildTarget={UnityEditor.EditorUserBuildSettings.activeBuildTarget}");
w.Add($"compressionFormat={UnityEditor.PlayerSettings.WebGL.compressionFormat}");
w.Add($"decompressionFallback={UnityEditor.PlayerSettings.WebGL.decompressionFallback}");
w.Add($"stripEngineCode={UnityEditor.PlayerSettings.stripEngineCode}");
w.Add($"managedStrippingLevel={UnityEditor.PlayerSettings.GetManagedStrippingLevel(target)}");
w.Add($"il2cppCodeGeneration={UnityEditor.PlayerSettings.GetIl2CppCodeGeneration(target)}");
w.Add($"apiCompatibilityLevel={UnityEditor.PlayerSettings.GetApiCompatibilityLevel(target)}");
w.Add($"exceptionSupport={UnityEditor.PlayerSettings.WebGL.exceptionSupport}");
w.Add($"debugSymbolMode={UnityEditor.PlayerSettings.WebGL.debugSymbolMode}");
w.Add($"dataCaching={UnityEditor.PlayerSettings.WebGL.dataCaching}");
w.Add($"wasm2023={UnityEditor.PlayerSettings.WebGL.wasm2023}");
w.Add($"initialMemorySize={UnityEditor.PlayerSettings.WebGL.initialMemorySize}");
w.Add($"maximumMemorySize={UnityEditor.PlayerSettings.WebGL.maximumMemorySize}");
w.Add($"memoryGrowthMode={UnityEditor.PlayerSettings.WebGL.memoryGrowthMode}");
w.Add($"targetFrameRate={UnityEngine.Application.targetFrameRate}");
w.Add($"vSyncCount={UnityEngine.QualitySettings.vSyncCount}");
return string.Join("\n", w);
正しい API 名を使う必要がある設定が 3 つあります。見た目から想像できる名前は存在せず、コンパイルに失敗するためです。
| 設定 | 正しい形式 | 存在しないもの |
|---|---|---|
| マネージドストリッピングレベル | PlayerSettings.GetManagedStrippingLevel(NamedBuildTarget.WebGL) | PlayerSettings.managedStrippingLevel |
| Wasm コード最適化 | UnityEditor.WebGL.UserBuildSettings.codeOptimization | PlayerSettings.WebGL.codeOptimization、PlayerSettings.WebGL.optimizationLevel |
| IL2CPP コード生成 | PlayerSettings.GetIl2CppCodeGeneration(NamedBuildTarget.WebGL) | 単独のプロパティ |
UserBuildSettings は WebGL ビルドサポートモジュールにあるため、そのモジュールがインストールされている場合にのみ解決されます。ほかの設定とは別の呼び出しで読み取り、解決に失敗した場合は、不正なコードではなく「Web モジュールがインストールされていない」と判断してください。
codeOptimization は、ここに挙げた設定のうちプロジェクトファイルに保存されない唯一の設定です。 Library/EditorUserBuildSettings.asset に保存されますが、Library/ は標準の Unity .gitignore で無視されるため、この値はマシンごとに異なり、共有されません。チームメンバーや CI に引き継がれることもありません。ここから 2 つのことがわかります。API 経由で値を読み戻し、ProjectSettings/ProjectSettings.asset を探さないでください。適用に成功してもそこには存在しないため、値がないことは失敗を意味しません。また、リリースビルドを CI で実行する場合、リポジトリに値が含まれていると想定せず、ビルドステップとして CI で適用してください。
設定の適用
このスキルで行う書き込みのほとんどは 1 回のバッチ処理で、scripts/WebOptimizer.cs がそのバッチ処理をすでに実行します。このファイルでは [MenuItem] を使ってクラスを宣言しているため、eval の入力ではなくプロジェクトファイルです。クラス宣言はステートメントブロックに変換できません。Assets/Editor/ に保存し、Unity のコンパイルを待ってから、1 行で実行してください。
UnityEditor.EditorApplication.ExecuteMenuItem("Tools/Apply Web Release Settings");
using ディレクティブはそのまま残してください。ファイル内では正しいものです。単発の変更、たとえば単一の品質レベルやフレームレートの切り替えには、インラインの eval ステートメントを使って問題ありません。
書き込んだオブジェクトではなく、ディスクから確認する
設定を適用して同じセッション内で読み戻しても、何も証明できません。 Player Settings は保存されるまでメモリ上のオブジェクトであるため、読み戻すと、ProjectSettings/ProjectSettings.asset に実際に反映されたかどうかにかかわらず、割り当てた値が返されます。保存を省略した実行でも成功と報告されますが、Editor セッションが終了すると変更はすべて失われます。これは推測ではなく、実際に確認された現象です。すべてを適用し、Brotli / High / None を読み戻して完了を報告した実行でも、ディスク上のファイルは変更されていませんでした。
そのため、書き込み後は次の手順を実行してください。
- 保存します。
UnityEditor.AssetDatabase.SaveAssets()を呼び出します。WebOptimizer.csはすでに自身で保存するようになっています。インラインのevalで書き込む場合は、明示的に保存する必要があります。 - 値を読み戻して報告します。 「適用に成功しました」ではなく、実際の値を報告して、ユーザーが保存内容を確認できるようにします。
WebOptimizer.csは 9 項目すべてをログに出力します。 - ビルドターゲットごとに設定される項目は、読み取った対象を明記します。 これらの設定のいくつかはターゲットごとに存在するため、あるターゲットでは正しい値でも、ビルド対象のターゲットでは未設定の場合があります。
ファイルを直接編集する場合にも、同じ落とし穴が逆向きに存在します。ProjectSettings.asset を手動で編集すると値は読み戻せますが、実行中の Editor とビルドは古い値を使い続けます。保存して再インポートした後に検証すれば、どちらの問題も検出できます。
バッチモードでこれを再現しようとしないでください。 -quit を指定して起動したバッチ Editor は終了時に設定を保存するため、保存していない書き込みも結果的に永続化され、実行は正しく見えます。保存するスクリプトと保存しないスクリプトのどちらも、-quit のもとでは成功します。この不具合が発生するのはライブ Editor セッションだけであり、実際に発見されたのもその環境です。不具合を検出できないテストでバッチ実行が成功したからといって、保存は不要だと結論づけるのは誤りです。
0. 事前確認
- Web ビルドターゲットを確認します: 上記の事前確認スニペットを使って
EditorUserBuildSettings.activeBuildTargetを読み取ります。値はWebGLである必要があります。そうでない場合は、ユーザーに警告してください。 - 圧縮とストリッピングの設定を読み取ります: 上記の事前確認スニペットを使って
compressionFormat、decompressionFallback、stripEngineCode、およびマネージドストリッピングレベルを読み取ります。ストリッピングレベルはPlayerSettings.GetManagedStrippingLevel(NamedBuildTarget.WebGL)です。PlayerSettings.managedStrippingLevelプロパティはありません。 - 例外処理と最適化の設定を読み取ります: 上記の事前確認スニペットを使って
PlayerSettings.WebGL.exceptionSupportを読み取ります。Wasm コードの最適化レベルにはUnityEditor.WebGL.UserBuildSettings.codeOptimizationを使います。PlayerSettings.WebGL.codeOptimizationとoptimizationLevelという表記は存在せず、コンパイルできません。 - フレームレート設定を読み取ります: 上記の事前確認スニペットを使って
Application.targetFrameRateとQualitySettings.vSyncCountを読み取ります。 - 追加のプレイヤー設定を読み取ります: 上記の事前確認スニペットを使って
PlayerSettings.WebGL.dataCaching、PlayerSettings.WebGL.debugSymbolMode、PlayerSettings.WebGL.maximumMemorySize、およびPlayerSettings.GetApiCompatibilityLevelを読み取ります。 - 圧縮、ストリッピング、フレームレート、およびプレイヤー設定を確認してから先に進んでください。
1. 現状を評価する
- ビルドレポートを確認します: ビルド後にユーザーに
Window > General > Build Reportを開いてもらい、サイズが最も大きいアセットとコードの要因を特定します。 - サーバー設定を確認します: ホスティングサーバーが
Content-Encoding: br(Brotli)またはContent-Encoding: gzipヘッダーを送信しているか、また.wasmファイルにContent-Type: application/wasmが設定されているかをユーザーに確認します。 - フレームレート設定を確認します: 上記の事前確認スニペットを使って
Application.targetFrameRateを確認します。Web ではブラウザーに任せるため、-1にする必要があります。 - メモリ設定を確認します: 上記の事前確認スニペットを使って
PlayerSettings.WebGL.initialMemorySizeとPlayerSettings.WebGL.memoryGrowthModeを読み取ります。 - 推奨事項を提示する前に、調査結果を報告してください。
2. リクエストを把握する
| ユーザーの発言 | デフォルトの解釈 |
|---|---|
| 「ビルドが大きすぎる」/「ダウンロードが遅すぎる」 | エンジンコードのストリッピングをオンにする。マネージドストリッピングを High にする。Disk Size + LTO を使う。Brotli を使う |
| 「Decompression Fallback」/「起動が遅い」 | Decompression Fallback をオフにする。Content-Encoding を送信するようサーバーを修正する |
| 「Chrome でカクつく」/「Safari でカクつく」 | ブラウザーの DevTools でプロファイルを記録する。Safari は 60 fps に制限される |
| 「ブラウザーでバッテリーを過剰に消費する」 | 静的な画面では OnDemandRendering をオンにする。targetFrameRate = -1 にする |
| 「例外処理のサイズが大きすぎる」 | リリースでは例外処理をなしにする。ブラウザーのベースラインが対応していれば Wasm 2023 の例外処理を使う |
| 「CDN を設定する」 | Addressables のリモートグループを使い、CDN で Brotli/Gzip を有効にする |
| 「WebAssembly 2023」 | ブラウザーのベースラインが対応したら有効にする。サイズが小さくなり、処理も速くなる |
| 「メモリの拡張が遅い」 | 初期メモリサイズをピーク時の推定値に合わせる。Geometric growth モードを使う |
| 「KTX」/「Basis Universal」/「GPU のテクスチャ形式が不明」 | Basis Universal を使った KTX2 を使う。サイズ重視なら ETC1S、品質重視なら UASTC を使う |
| 「未使用コードをストリッピングする」/「未使用パッケージを削除する」 | Web Stripping Tool を使い、未使用パッケージを削除し、シェーダーをストリッピングする |
| 「Web 向けの品質設定」 | Quality Level を Very Low または Low にする。品質を下げるほど読み込みが速くなる |
| 「シェーダーバリアントが多すぎる」 | Graphics 設定でライトマップモードとフォグモードを自動にする。インスタンシングと BRG のバリアントをストリッピングし、Always Included Shaders を監査する |
| 「動画が再生されない」/「音声の問題」 | 動画:URL のみ、または StreamingAssets を使う。音声:Web では AudioEffects を使わず、Mono を使って圧縮する |
| 「プロファイラーのシンボル」/「Wasm のスタックを読み取れない」 | ビルドプロセッサーまたは emscriptenArgs を使ってプロファイリングシンボルを埋め込む |
| 「iOS でクラッシュする」/「Safari のメモリ」 | iOS のメモリ制限を考慮する。拡張するより初期メモリサイズを大きく設定する。iOS 18 より前は Gigacage の上限が 2GB |
3. Web ビルド最適化のワークフロー
重要:ワンクリック最適化スクリプト
このスクリプトを生成することを必ずユーザーに提案してください。 Unity の公式 Web 最適化ドキュメントには、推奨されるリリース設定を一度にすべて適用する、エディターメニュー用のスクリプトが用意されています。Assets/Editor/WebOptimizer.cs に配置してください。テンプレートについては、scripts/WebOptimizer.cs を参照してください。
ユーザーのプロジェクトの要件に合わせてスクリプトを調整してください(例:try/catch を使用している場合は例外処理を有効にする、HTTP ホスティングでは Brotli を Gzip に切り替える)。このスクリプトは、新しい Web プロジェクトで最も効果の大きい単一の対策です。設定の見落としを防げます。
Player Settings の監査
eval を通じて次の値を確認し、設定してください。
| 設定 | リリース時の推奨値 |
|---|---|
| Compression Format | Brotli(HTTPS ホスティング);HTTP の場合は Gzip |
| Decompression Fallback | サーバーが正しく設定されている場合は オフ |
| Strip Engine Code | オン |
| Managed Stripping Level | High(リリース)/Medium(開発) |
| Code Optimization | Disk Size with LTO(リリース)/Build Times(開発) |
| WebAssembly Language Features | ブラウザーのベースラインが対応している場合は 2023 |
| Enable Exceptions | None(最小サイズ);try/catch が必要な場合は Explicitly Thrown Only |
| Initial Memory Size | ピーク時の推定値に合わせて調整します。小さすぎると拡張コストが高くなります |
| Memory Growth Mode | Geometric |
| API Compatibility Level | .NET Standard 2.1 — .NET Framework より小さいサイズです |
| IL2CPP Code Generation | Optimize Size — 実行時コストがわずかに増える代わりに、Wasm のサイズを小さくします |
| Debug Symbols | リリースでは オフ;開発ビルドでのみオン |
| Data Caching | オン — アセットデータをブラウザーの IndexedDB にキャッシュし、再読み込みを高速化します |
| Strip Unused Mesh Components | オン — 未使用の頂点属性を削除します |
| Maximum Memory Size | デフォルトは 2048 MB;複雑な 3D では最大 4096(Firefox と Chrome < 119 では 2048 を超えると問題が発生します) |
| vSyncCount | 0(ブラウザーがペースを制御します) |
| targetFrameRate | -1(requestAnimationFrame を使用します) |
圧縮とサーバー設定
| 圧縮方式 | 使用する状況 | 備考 |
|---|---|---|
| Brotli | HTTPS または localhost | 最も高い圧縮率です。ブラウザーが受け付けるのはセキュアコンテキストのみです |
| Gzip | HTTP 配信、レガシー CDN | 広く利用できます |
| None | ローカル開発/file:// | ペイロードが最大になります。リリースには使用しないでください |
サーバーを次のように設定してください。
.brファイルをContent-Encoding: brで配信します。.gzファイルをContent-Encoding: gzipで配信します。.wasmにはapplication/wasm、.jsにはapplication/javascriptのContent-Typeを設定します。- チャンクの取得を並列化するため、HTTP/2 または HTTP/3 を有効にします。
ホスト側で Content-Encoding を付与できない場合は、フォールバックとしてのみ Decompression Fallback = On に設定してください。約 150 KB の JS が追加され、起動が遅くなります。
例外処理
| 設定 | ビルドサイズ | 使用場面 |
|---|---|---|
| None | 最小 | 未処理例外を許容できるリリースビルド |
| Explicitly Thrown Only | やや増加 | 例外をキャッチするプロジェクトのデフォルト |
| Full | 最大、最も低速 | 必要になることはまれです。リリースでは避けてください |
Wasm 2023 では、より低コストな例外モデルが導入されています。ブラウザーのターゲットが対応している場合、Explicitly Thrown Only(従来方式)から Wasm 例外に切り替えると、サイズとコストの両方を削減できます。
未使用のリソースを削除する
ビルドサイズを削減するために監査する3つのカテゴリ:
1. 未使用のパッケージ — Packages/manifest.json と、Package Manager の In Project および Built-in ビューを確認します。プロジェクトで使用していないパッケージは削除するか、無効にしてください。Input System パッケージを使用していない場合、サイズを大きくする要因になります。
2. シェーダーのストリッピング — Edit > Project Settings > Graphics で設定します:
| 設定 | 推奨事項 |
|---|---|
| Lightmap Modes | Automatic(未使用のライトマップシェーダーバリアントをストリップします) |
| Fog Modes | Automatic(未使用のフォグシェーダーバリアントをストリップします) |
| Instancing Variants | Strip Unused |
| Batch Renderer Group Variants | Strip All(BRG を使用していない場合) |
| Always Included Shaders | 監査し、プロジェクトが参照していないシェーダーを削除します |
ストリッピング後にテストし、参照されているシェーダーを削除していないことを確認してください。
3. Web Stripping Tool(com.unity.web.stripping-tool)— WebAssembly バイナリを分析し、未使用の Unity エンジンサブモジュール(例:2D 専用ゲームでの3Dグラフィックス)を特定します。Package Manager からインストールし、ビルドをプロファイリングしてから、除外するサブモジュールを設定します。Managed Stripping Level 単独の場合を超える、大幅なサイズ削減が期待できます。
Web 向けの品質設定
品質レベルを下げると、読み込み時間が短縮され、実行時のパフォーマンスが向上します。Edit > Project Settings > Quality で設定します:
- Web のデフォルト品質レベルには Very Low または Low を使用します。
evalで設定します:UnityEngine.QualitySettings.SetQualityLevel(0, true);(0 = Very Low)。- ブラウザー内では不要な機能(リアルタイムシャドウ、ポストプロセスエフェクト、多数のパーティクルなど)を無効にする、Web 専用の品質レベルを作成することを検討してください。
Web でのフレームレート
evalで設定します:UnityEngine.Application.targetFrameRate = -1;— ブラウザーのrequestAnimationFrameを使用します。- 注意:Safari は WebGL で 60 fps に制限されます。高リフレッシュレートのターゲットは適用されません。
- 静的画面やアイドル画面では
OnDemandRendering.renderFrameIntervalを使用して 5~10 fps に下げ、バッテリーを節約します。
KTX / Basis Universal テクスチャ
Basis Universal の超圧縮を使用した KTX2 は、単一のテクスチャファイルを配布し、読み込み時にブラウザーのデバイスに最適な GPU フォーマット(デスクトップでは BC7、モバイルでは ASTC、古い Android では ETC2)にトランスコードします。GPU ファミリーごとに別々のテクスチャバリアントを配布する必要がなくなります。ターゲットハードウェアが不明な Web では特に重要です。
| トピック | ガイダンス |
|---|---|
| パッケージ | Package Manager から com.unity.cloud.ktx(KtxUnity)をインストールします |
| 使用する場合 | Addressables 経由で実行時に読み込むテクスチャ、または不特定の GPU ターゲット向けに配信するアセットバンドル |
| 使用しない場合 | プレイヤービルドに組み込まれたテクスチャ — Unity がビルド時に適切なフォーマットをすでに選択しています |
| 超圧縮 | 最小サイズにする場合は ETC1S(非可逆、ディフューズ/アルベドに適しています)、高品質にする場合は UASTC(ほぼ可逆、法線/UI に適しています)を使用します |
| エンコード | toktx または basisu CLI でオフラインエンコードします。実行時にはエンコードしないでください |
| リニアデータ | 法線マップ、マスク、またはデータテクスチャをエンコードする際は、sRGB 変換の誤りを防ぐため --assign_oetf linear を設定します |
| ミップマップ | エンコード時にミップマップを生成します(--genmipmap)。ブラウザー側でのミップマップ生成は高コストです |
| 読み込み | KtxTexture.LoadFromStreamingAssets を使用するか、UnityWebRequest でバイト列を読み込んで KtxTexture.LoadFromBytes を呼び出します |
| メモリ | トランスコードされたテクスチャは標準の GPU テクスチャです。メモリ使用量は KTX2 ファイルサイズではなく、ターゲットフォーマットのサイズに相当します |
| 向き | Unity の UV 規約に合わせるため、必ず --lower_left_maps_to_s0t0 を含めます |
toktx CLI の例: アルベド(ETC1S)、法線/ディテール(UASTC)、ICC プロファイルエラー、リニアデータに対応するコマンドについては、scripts/toktx-examples.sh を参照してください。
Web でのストリーミング
- CDN でホストし、Brotli / Gzip で圧縮したリモートグループで Addressables を使用します。
- ゲーム全体を初回ダウンロードに含めるのは避け、レベルを必要に応じてストリーミングします。
- 「インスタントプレイ」向けに、初回ダウンロードを 30 MB 未満に抑えます。レベルデータはその後に読み込みます。
- 異なる GPU ハードウェアを対象にテクスチャをストリーミングする場合、プラットフォームごとのバリアントより KTX2 バンドルを優先します。1 つのバンドルですべてのブラウザーに対応できます。
Web ビルドのプロファイリング
| ツール | 用途 | 備考 |
|---|---|---|
| Chrome DevTools > Performance | CPU フレームグラフ、メインスレッドの分析 | WebGL のカクつきが発生した際に最初に確認します。Wasm のコールスタックを調べます |
| Chrome DevTools > Memory | ヒープスナップショット、割り当てタイムライン | JS/Wasm のメモリリークを特定します。シーンの読み込み前後でスナップショットを比較します |
| Firefox Profiler | クロスプラットフォーム対応、共有可能な URL、ネイティブと Wasm の表示 | 場合によっては Chrome より Wasm のシンボル解決に優れています。チームレビュー用にプロファイル URL を共有できます |
| Safari Web Inspector | iOS Safari と macOS Safari のデバッグ | Safari 固有の問題には必須です。WebGL/Wasm ランタイムは Chromium と異なります |
| WebSocket 経由の Unity Profiler | 開発ビルドに接続し、標準マーカーを表示 | Unity 側のマーカー(GC、レンダリング、スクリプト)に使用します。ブラウザー側のオーバーヘッドは取得しません |
症状別のツール早見表:
| 症状 | 最初に使うツール | 次に使うツール |
|---|---|---|
| WebGL の引っかかり/カクつき | Chrome DevTools > Performance | Firefox Profiler |
| 時間の経過とともにメモリが増加する | Chrome DevTools > Memory | Unity Memory Profiler (WebSocket) |
| 初回読み込みが遅い | Chrome DevTools > Network | Build Report Inspector |
| Safari のみで発生するレンダリングの問題 | Safari Web Inspector | Chrome DevTools と比較 |
プロファイリングシンボルの埋め込み — ブラウザのプロファイラーでは、デフォルトで難読化された Wasm 関数名が表示されます。Chrome/Firefox のフレームグラフで読みやすい C# メソッド名を表示するには、開発ビルドで Player Settings > Publishing > Debug Symbols を有効にするか、ビルドプロセッサーを追加します。
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
public class WebProfilingBuildProcessor : IPreprocessBuildWithReport
{
public int callbackOrder => 0;
public void OnPreprocessBuild(BuildReport report)
{
PlayerSettings.SetAdditionalIl2CppArgs("--compiler-flags=--profiling-funcs");
}
}
Emscripten 組み込みプロファイラー — PlayerSettings.WebGL.emscriptenArgs で一度に 1 つだけ有効にします。
| フラグ | 表示内容 |
|---|---|
--cpuprofiler | ブラウザー内の CPU プロファイラーオーバーレイ |
--memoryprofiler | 視覚的なメモリマップ(白=割り当て済み未使用、ピンク=スタック、青=動的、緑=断片化) |
--threadprofiler | スレッドアクティビティプロファイラー |
GPU デバッグ — Web では Frame Debugger をサポートしていません。ブラウザーベースの代替手段として Spector.js を使用します。描画呼び出しと WebGL の状態を取得できます。
Firefox の about:memory — Firefox の URL として about:memory を入力し、Measure をクリックすると、タブごとの内訳(WASM コードサイズ、WASM ヒープ、.data ファイル、Web Audio)を確認できます。WASM ヒープが 300 MB を超えていないか注意してください(特に iOS Safari ではクラッシュのリスクがあります)。
エディターの Play モードはブラウザーのランタイムを再現しません。必ずブラウザーで計測してください。Chrome と Safari では GC と JIT の動作が異なるため、両方でテストしてください。
Web のメモリに関する指示
- テクスチャとメッシュのRead/Write Enabledを無効にします。有効にすると、データが WASM ヒープに複製されます。
- アセットを Addressables または AssetBundles に移動して、
.dataファイルのサイズを小さくします。 - 圧縮テクスチャ形式(KTX2/Basis)を使用して、ダウンロードサイズとデコード後のメモリ使用量の両方を削減します。
iOS Safari のメモリ制限
- iOS < 18: WebContent プロセスの上限は約 1.5 GB です。WASM メモリ(Gigacage)の上限は 2 GB です。型付き配列はこのメモリプールを共有します。iPhone X(iOS 16)ではヒープの拡張上限は約 512 MB ですが、Initial Memory Size を事前に 512 MB~1.5 GB に設定すれば動作します。
- iOS 18 以降: 制限はほぼ撤廃されています。iPhone 11 では約 4 GB を割り当てられます。
- iOS では、拡張に頼らず、目標とするピーク値に合わせてInitial Memory Sizeを設定します。Safari は、段階的な拡張よりも大きなメモリを事前に割り当てるほうが適切に処理できます。
- 古い iOS では、WASM ヒープが 300 MB を超えるとクラッシュのリスクが高まります。幅広い互換性を確保するため、200 MB 未満を目標にします。
Web 上的视频和音频
- 動画: 再生できるのは、URL(CORS が有効になっているサーバー)または StreamingAssets からのみです。iOS でストリーミングするには、サーバーが HTTP の Range リクエストに対応している必要があります。ブラウザー互換の形式(MP4/H.264)を使用してください。
- 音声: AudioEffects(ミキサーエフェクト)にはコンピュートシェーダーが必要です。WebGL では利用できません。ミキサーと MixerGroups は音量調整にのみ使用できます。読み込みを改善するには、音声を Mono に設定してください。
about:memoryで Web Audio が 100 MB を超えている場合、音声が非圧縮である可能性があります。Vorbis に切り替えてください。
Canvas と DPI
Canvas を拡大すると、新しい解像度が適用されます。Web テンプレートで devicePixelRatio を使用して DPI スケーリングを補正し、不必要に高い解像度でのレンダリングを避けてください。
4. 検証
- Pre-Flight スニペットを使って Player Settings を再確認します(圧縮、ストリッピング、例外、targetFrameRate)。
- プレイヤーを再ビルドし、Build Report のファイルサイズをベースラインと比較します。
- 少なくとも Chrome と Safari で確認します(GC と JIT の挙動は異なります)。
- ユーザーにフィードバックを求めるまでの反復は最大 3 回です。
5. トラブルシューティング
Strip Engine Code を有効にしてもビルドが大きい
- Managed Stripping Level が Medium または Low に設定されていますか? → リリースでは High に設定します。
- プラグインがリフレクションを使って、本来ならストリッピングされるエンジンモジュールにアクセスしていますか? → 必要なシンボルを保持するために
link.xmlを追加します。 - Exceptions が Full に設定されていますか? → Full はコードのオーバーヘッドが最も大きくなります。None または Explicitly Thrown Only に切り替えます。
Brotli が機能しない — Decompression Fallback が必要
- サーバーは
Content-Encoding: brを送信していますか? → このヘッダーがないとブラウザーは展開できず、フォールバック用の JS デコンプレッサーが必要になります。 - ビルドは HTTP(HTTPS ではなく)でホストされていますか? → Brotli にはセキュアコンテキストが必要です。HTTP でホストする場合は Gzip に切り替えます。
Chrome では問題ないが、Safari でカクつく
- プロジェクトで
Application.targetFrameRate = 60が設定されていますか? → Safari WebGL ではブラウザーのフレーム制御と競合します。-1に設定します。 - Safari の WebGL 実装で異なる動作をするシェーダーがありますか? → デバイスでテストしてください。Safari の WebGL/Wasm ランタイムは Chromium と異なるため、一部の GLSL 構文の扱いも異なります。
メモリ拡張の低速パスが発生する
- Initial Memory Size がプロジェクトのピークに対して小さすぎますか? → Wasm のメモリ拡張ではバッファー全体のコピーが必要です。Initial Memory Size を現実的なピーク推定値に設定します。
- Memory Growth Mode が Linear に設定されていますか? → より適切な増加曲線になるよう、Geometric に切り替えます。
フレームレートを 60 に設定しているのに、ブラウザーの動作が不安定
- コードで
Application.targetFrameRate = 60が設定されていますか? → Web ではブラウザーのrequestAnimationFrameによるフレーム制御と競合します。-1に設定します。 vSyncCountが 0 以外ですか? → 0 に設定します。フレーム制御はブラウザーが行います。
Firefox が大きなファイルをキャッシュできない
Firefox は browser.cache.disk.max_entry_size によって、キャッシュエントリーごとのサイズを制限しています。ビルドがこの上限(デフォルトで約 50 MB)を超えると、アセットはキャッシュされません。対処法:Addressables を使って 51 MB 未満のバンドルに分割するか、ユーザーに about:config で設定を増やすよう案内します。
ローカル開発サーバーのセットアップ
適切な MIME タイプでビルドをローカルテストするには:
# Python (HTTP)
python -m http.server 55553 -d path/to/build
# Node.js (install serve-handler)
npx serve path/to/build -l 3001
Brotli のテストには HTTPS を使用してください。Brotli にはセキュアコンテキストが必要です。ローカルテスト用に OpenSSL で自己署名証明書を生成します。
最終ステップ
Web の設定はブラウザーのビルドでのみ有効になるため、クリーンコンパイルと Editor での Play モードだけでは不十分です。以下の確認を順番に実行してください。いずれかの確認に失敗した場合は、ドキュメントのページを読み直して見落とした点を確認し、修正してから再度確認してください。
- プロジェクトにコンソールエラーが一切ないことを確認します。
- 変更した各設定が保存されていることを、ディスクから確認する(書き込んだばかりのオブジェクトから確認しない)の説明に従って確認します。
ProjectSettings/ProjectSettings.assetに新しい値が保持されており、codeOptimizationは API 経由で読み取れる必要があります。 - Player を再ビルドした場合は、ローカル開発サーバーのセットアップの説明に従ってビルドを配信し、ブラウザーで開きます。その後、以下を確認します。
- ブラウザーのコンソールに、圧縮解除の失敗やメモリ不足エラーなどのエラーが表示されていないこと。
- Network タブで、
.wasm、.data、.framework.jsファイルのContent-Encodingヘッダーが圧縮形式(Brotli の場合はbr、Gzip の場合はgzip)に一致し、ファイルサイズが Build Report と一致していること。
- フレームレートや品質レベルなど、変更がランタイムの動作に影響する場合は、ブラウザーのコンソールで
Debug.Logの行を確認してから削除します。スクリーンショットの撮影と確認は、どうしても必要な場合を除き避けてください。時間がかかるためです。
最終レポート
実施したこととその理由を、簡潔ながらも内容の詰まりすぎていないチェックリストでユーザーに伝えます。以下を含めてください。
- 変更前後のダウンロードサイズと、変更した各設定(圧縮、ストリッピング、例外、
targetFrameRate)の旧値と新しい値。 - プロジェクトに追加したスクリプト(例:
Assets/Editor/WebOptimizer.cs)、変更した品質レベル、またはマシンごとに保存され、チームメンバーや CI には引き継がれない設定(codeOptimization)などの副作用。 - 再ビルドなしでのブラウザーテストや、Editor を利用できなかった場合のすべての確認など、実施しなかった確認と、置いた前提。
ユーザーに追加の手順や判断が必要な場合は、Addressables のリモートグループに対する CDN のセットアップ、Safari でのテスト、ブラウザーの基準環境が対応した際に Wasm 2023 の機能セットへ移行することなどを挙げます。例:
I made the following changes:
[✓] Set Compression Format to Brotli and Strip Engine Code to on, because the server sends `Content-Encoding: br` over HTTPS.
[✓] Added `Assets/Editor/WebOptimizer.cs`, which applies the release settings from Tools > Apply Web Release Settings.
Follow these steps to finish:
1. Apply `codeOptimization` in your CI build step, because it's stored in `Library/` and doesn't travel with the project.
2. Test the build in Safari, because its garbage collection and JIT behaviour differ from Chrome.
関連項目
このスキルの範囲を超えるタスクについては、以下の Unity ツールを案内します。
- Addressables パッケージ — ダウンロード予算に合わせてコンテンツを初期ペイロードから移す必要がある場合に、CDN 経由でリモートグループを配信します。
- ブラウザーに接続した Unity Profiler — クロスプラットフォームのプロファイリング手法です。セクション 3 では、接続方法の Web 固有の部分を説明しています。
- シェーダーバリアントのストリッピング(Graphics settings → Shader Stripping、
ShaderVariantCollection)— バリアント数は Wasm サイズに直接影響するため、ストリッピングだけではサイズが減らなかった場合に確認する価値があります。 - Project Settings → Player — このスキルが読み取るものと同じフラグを確認できます。インスペクターで見たいユーザーに案内してください。
- モバイルブラウザーのバッテリー動作にも、セクション 3 と 4 のフレームレートおよび品質レベルに関するガイダンスが適用されます。ここではモバイル専用の手順はありません。