optimize-web について
Unity の Web ビルドサイズとパフォーマンスに関わる設定を監査、調整する開発スキルです。プロジェクトのバージョンに合わせたドキュメントを参照し、基準値と復元ポイントを用意してから範囲を限定して変更します。
主な機能
- 01Web Player 設定の監査
- 02圧縮とコードストリッピングの調整
- 03未使用リソースとシェーダーバリアントの確認
- 04デプロイとメモリ設定の確認
- 05基準値との比較による変更検証
活用シーン
- 01Unity Web ビルドサイズの削減
- 02圧縮とコードストリッピング設定の見直し
- 03Web ビルドのサーバー要件の確認
- 04Web ビルドのメモリ制約の診断
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ unity-technologies/ unity-agent-plugin --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 します。ファイル全体を読み込まないでください。
手順
- プロジェクトのコンテキストを確認します。Unity のバージョンは
ProjectSettings/ProjectVersion.txtから、必要なパッケージ(com.unity.cloud.ktx、com.unity.addressables、com.unity.web.stripping-tool)のバージョンはPackages/packages-lock.jsonから取得します。プロジェクトがない場合は、Unity6000.0と仮定します。packages-lock.jsonに記載されていないパッケージは、そのパッケージのドキュメントにある最新バージョンと仮定します。確認できたバージョンはすべてそのまま使用し、実際に不足している値だけを既定値で補います。レポートには仮定した内容をそれぞれ明記して、作業を続けます。ユーザーが何を最適化したいかを示しておらず、参照できるプロジェクトもない場合は、何を改善したいか尋ねます。 - トピックの全体マップから、タスクに該当するドキュメントページを読みます。
- エディターでの C# 実行の説明に従って
script evalをセットアップします。エディターに接続できない場合、またはscript evalがない場合は、その旨を伝えて手順 5 に進み、その後は手順 9 に進みます。レポートでは、ビルド検証とランタイムチェックを未実施とし、手順 2 のユーザーの依頼とドキュメントに基づいて推奨事項を提示します。 - 0. 事前確認と1. 現状の評価を実行します。結果をベースラインとします。
- 依頼内容に該当する行を2. 依頼内容の把握から選びます。
- 復元ポイントを作成してから、3. Web ビルド最適化ワークフローに記載された変更を適用します。症状が5. トラブルシューティングに該当する場合は、その項目に従います。
- 4. 検証を実行し、事前確認のスニペットを再実行して、値をベースラインと比較します。
- 最終手順に記載されたチェックを行います。
- 最終レポートを提出します。
エディターでの C# 実行
以下の各手順で、プレーヤー設定の読み取りや書き込みを行う際は、Unity CLI を介して起動中のエディター内で実行します。接続を確立する役割は unity-cli スキルが担います。CLI のインストール、接続済みエディターの確認、プロジェクトへの com.unity.pipeline パッケージの追加、エディターが本当に存在しない場合とセーフモードで停止している場合の見分け、エディターのコマンドカタログの確認は、このスキルに従ってください。まずスキルの手順を実行し、ここで内容を再確認しないでください。
次の 2 点は、このスキルでは判断できません。
- 接続可能なエディターだけでなく、特に
script evalが必要です。 コマンドカタログに表示されていることを確認してください。利用できるかどうかは CLI ではなく Pipeline パッケージのバージョンによって決まるため、インストールが正常でも利用できない場合があります。見つからない場合はその旨を伝え、設定の読み取りや書き込みを行う手順を省略してください。 - いざというときは
ProjectSettings/ProjectSettings.assetからプレーヤー設定を読み取れますが、その方法で書き込んではいけません。 シリアライズされた名前は API の名前と一致せず、設定の一部はビルドターゲットごとに異なり、手動で編集した値は実際のビルドで使用される値と知らないうちに食い違う可能性があります。エディターに接続できない場合は、書き込みを行う手順に進めません。
unity command script eval --caller plugin --skill optimize-web --code '<snippet>' を使用して C# を実行します。unity command のタイムアウトは既定で 30 秒です。
script eval に渡す C#
script eval がコンパイルするのはファイルではなくステートメントブロックです。そのため、コードには using ディレクティブを含めず、型名は完全修飾名で記述してください。コードをコンパイルできない場合は、次の表でエラーを確認してください。
| エラー | 原因 | 修正方法 |
|---|---|---|
CS0210 | using UnityEditor; のような using ディレクティブが含まれています。コンパイラーがこれをリソース破棄のステートメントとして読み取ります | ディレクティブを削除し、型名を完全修飾します |
CS0246 | PlayerSettings のような修飾されていない型名が含まれています | UnityEditor.PlayerSettings のように完全修飾名を使用します |
CS0104 | 裸の Object が object と曖昧になっています | UnityEngine.Object を使用します |
このスキルが監査する設定の読み取り
1 回の呼び出しで、Pre-Flight の全体像を取得できます。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 に保存されます。標準的な Unity の .gitignore ではすべて Library/ が Git の管理対象外となるため、この値はマシンごとに異なり、共有されません。チームメンバーや CI に引き継がれることもありません。結果として、次の 2 点に注意が必要です。API 経由で値を読み戻し、ProjectSettings/ProjectSettings.asset 内では探さないでください。適用に成功していてもそこには存在しないため、見つからなくても失敗ではありません。また、リリースビルドを CI で実行する場合は、リポジトリに値が含まれていると考えず、ビルド手順として CI 上で設定してください。
設定の適用
このスキルでの書き込みのほとんどは 1 つのバッチで実行でき、scripts/WebOptimizer.cs はすでにそのバッチになっています。このファイルでは [MenuItem] を含むクラスを宣言しているため、script eval の入力ではなく、プロジェクトファイルです。 クラス宣言をステートメントブロックに展開することはできません。Assets/Editor/ に保存して Unity にコンパイルさせてから、1 行で実行してください。
UnityEditor.EditorApplication.ExecuteMenuItem("Tools/Apply Web Release Settings");
using ディレクティブはそのまま残してください。ファイル内では正しい記述です。単発の変更(単一の品質レベルやフレームレートの切り替えなど)には、インラインの script eval ステートメントを使用できます。
書き込んだオブジェクトではなく、ディスクから検証する
設定を適用した直後に同じセッションで読み戻しても、何の証明にもなりません。 Player Settings は保存されるまでメモリ上のオブジェクトであるため、値を読み戻すと、ProjectSettings/ProjectSettings.asset に反映されたかどうかにかかわらず、割り当てた値が返されます。保存を省略した実行でも成功と報告されますが、Editor セッションが終了すると変更はすべて失われます。これは仮説ではなく、実際に確認されています。すべての設定を適用し、Brotli / High / None を読み戻して完了と報告したにもかかわらず、ディスク上のファイルは変更されていませんでした。
そのため、書き込み後は次の手順を実行してください。
- 保存します。
UnityEditor.AssetDatabase.SaveAssets()を呼び出します。現在のWebOptimizer.csは内部で保存しますが、インラインのscript 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 公式のウェブ最適化ドキュメントには、推奨されるすべてのリリース設定を一度に適用する単一のエディターメニュースクリプトが用意されています。Assets/Editor/WebOptimizer.cs に配置してください。テンプレートは scripts/WebOptimizer.cs を参照してください。
ユーザーのプロジェクトのニーズに合わせてスクリプトを調整してください(例:try/catch を使用している場合は例外処理を維持する、HTTP ホスティングでは Brotli を Gzip に切り替える)。このスクリプトは、新しいウェブプロジェクトで最も効果の大きい対策です。設定の見落としを防ぎます。
Player Settings の監査
script eval を使用して、以下の値を確認し設定してください。
| 設定 | リリース時の推奨値 |
|---|---|
| Compression Format | Brotli(HTTPS ホスティング);HTTP の場合は Gzip |
| Decompression Fallback | サーバーが正しく設定されている場合は Off |
| Strip Engine Code | On |
| 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 | リリースでは Off、開発ビルドのみ On |
| Data Caching | On — アセットデータをブラウザーの IndexedDB にキャッシュし、再読み込みを高速化します |
| Strip Unused Mesh Components | On — 未使用の頂点属性を削除します |
| 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にはContent-Type: application/wasm、.jsにはapplication/javascriptを設定します。- HTTP/2 または HTTP/3 を有効にして、チャンクの取得を並列化します。
ホスト側で Content-Encoding を挿入できない場合は、フォールバックとしてのみ Decompression Fallback = On に設定してください。約 150 KB の JS が追加され、起動も遅くなります。
例外処理
| 設定 | ビルドサイズ | 用途 |
|---|---|---|
| None | 最小 | 未捕捉の例外を許容できるリリースビルド |
| Explicitly Thrown Only | 小 | 例外を捕捉するプロジェクトのデフォルト |
| Full | 最大、最も低速 | 必要になることはまれです。リリースでは避けてください |
Wasm 2023 では、より低コストな例外モデルが導入されています。ブラウザーのターゲットが対応している場合、Explicitly Thrown Only(レガシー)から Wasm exceptions に切り替えると、サイズとコストの両方を削減できます。
未使用のリソースを削除する
ビルドサイズを削減するために、次の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 を使用します。
script evalで設定します:UnityEngine.QualitySettings.SetQualityLevel(0, true);(0 = Very Low)。- ブラウザー内で不要な機能(リアルタイムシャドウ、ポストプロセスエフェクト、多数のパーティクルなど)を無効にする、Web 専用の品質レベルを作成することを検討してください。
Web でのフレームレート
script 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 でオフラインエンコードします。実行時にエンコードしないでください |
| リニアデータ | 法線マップ、マスク、データテクスチャをエンコードするときは --assign_oetf linear を設定し、誤った sRGB 変換を防ぎます |
| ミップマップ | エンコード時にミップを生成します(--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 のフレームレートおよび品質レベルに関するガイダンスが適用されます。ここではモバイル専用の手順はありません。