scenario-unity-mobile について
モバイルゲーム開発者向けの Unity スキルで、性能、アセットのインポート、入力と UI、マネタイズ、ストア公開を扱います。継続動作時の挙動と実際のビルド成果物を重視し、Android と iOS の検査・リリース手順を備えています。
主な機能
- 01継続フレームレートと熱を評価
- 02モバイル描画とアセット形式を監査
- 03タッチ入力とセーフエリア UI を構築
- 04購入、広告、プライバシー処理に対応
- 05Android と iOS のリリース成果物を検査
活用シーン
- 01低価格帯スマートフォンのフレーム予算を設定・検証
- 02テクスチャ、音声、描画設定を調整
- 03セーフエリア配置とタッチ操作をテスト
- 04購入、報酬、広告コールバックの処理を確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ scenario-labs/ skills --skill scenario-unity-mobileインストール後、Claude Code で/scenario-unity-mobileを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/critique.mdexpert-notes.mdgui-paths.mdprocedures.mdsources.mdscripts/ut_mobile.pyscripts/AgentKit/Mobile/MobileAudio.csMobileBuild.csMobileImportRules.csMobileStartup.csMobileTextures.csMobileTiers.csMobileUi.csMobileXcodePostprocess.csscripts/Runtime/AgentKit.Mobile.Runtime.asmdefAndroidDiagnostics.csDeviceSoakLogger.csMobileTierPolicy.csMonetization.csSafeAreaFitter.csSafeAreaMath.csTouchStick.csscripts/Runtime/Iap5/AgentKit.Mobile.Iap5.asmdefIap5Store.csscripts/Runtime/LevelPlay9/AgentKit.Mobile.LevelPlay9.asmdefLevelPlayAds.cs詳細
Unity モバイル(モバイル専門家)
モバイルの専門的な作業とは、3年前のスマートフォンで20分プレイしてもフレームレートを維持し、すばやく起動し、ストアからインストールでき、二重請求や二重付与が決して起きないゲームを作ることです。基本方針は、持続可能なフレームを基準に予算を組み、デバイスに届くデータ(インポート形式、ビルド済みバンドル、エクスポートした Xcode プロジェクト)であらゆる設定を検証し、ストア、SDK、課金コードを厄介なイベント順序を伴う契約として扱うことです。対象環境:Unity 6000.3.21f1、URP 17.3、Input System 1.20、Xcode 26.6 を搭載した macOS。この項目に記載されている関連スキルが利用可能なスキルにない場合は、ユーザーにインストールを依頼してください(npx skills add scenario-labs/skills --skill <name>)。無人で作業する場合は、ツールのスキーマに基づいて進め、不足しているスキルがあることを明記してください。
必須の背景知識: scenario-unity-expert(チャンネル、レビューループ、6.3 の落とし穴)。ツールキット:
scripts/ut_mobile.py(ut_env、ut_run、ut_stat をインポート)、エディタージョブは
scripts/AgentKit/Mobile/、プレイヤーコードは
scripts/Runtime/ にあります。
基本方針(専門知識による追加事項)
- ピークではなく、持続可能なフレーム予算を設定します。 1000/fps の約65%を目安にします(60 fps では10.8 ms、30 fps では21.7 ms)。最も性能の低いスマートフォンで、短時間のバーストと10~15分の冷却時間を含め、p95 と最大値で評価します。VSync を前提としてください。リフレッシュを1回逃すと、フレームレートは半分になります(Unity モバイル e-book)。熱が発生したら、GPU がボトルネックの場合に限り、まずレンダリングスケールを下げます。CPU バウンドのフレームでは、解像度を下げてもほとんど効果がありません(6.3 Manual)。過熱したスマートフォンではなく、合成サーマルイベントを使ってポリシーを検証してください(d5O4Uw6gPBI [00:04:21])。エディターのタイミングは相対値です。エディターで安定した証拠となるのは、ドローコール数と SetPass 数です(観察結果)。
- 実効フォーマットを確認してから、ルールを固定します。 GPU がサンプリングできないテクスチャは、CPU 上で RGBA32 に展開されます(6.3 Manual)。ASTC HDR のオーバーライドを設定せずにインポートした HDR マップは、ETC2_RGBA8 としてインポートされました(観察結果)。UI と顔には ASTC 4x4、デフォルトには 6x6、大きな環境マップには 8x8 を使います[追加]。ASTC では Crunch は効果がありません。オーディオ:ソースには WAV、モノラルの効果音は最大22,050 Hz、200 KB 未満なら ADPCM、約400 KB を超える場合のみ Streaming を使います(e-book)。
AssetPostprocessorで新しいアセットが準拠するようにします(Unity Enterprise Support、j4YAY36xjwE [00:19:07])。 - モバイル向け URP は、スライダーを低くした PC 向け URP ではありません。 Depth Priming は無効(Android、iOS、TBDR では非対応)、Native RenderPass は有効、Depth と Opaque テクスチャはサンプリングしない限り無効、HDR は無効または32ビット、ソフトシャドウは無効、Store Actions は Auto または Discard にします(6.3 Manual)。Quality ティアごとに URP アセットを1つ用意します。Android 向けに起動したバッチエディターが、Quality「PC」と報告した事例があります(観察結果。同じ落とし穴が 2J0kDtUGlrY [frame 00:10:28] にもあります)。
- リリースビルドは環境から再現可能にします。 Unity はキーストアのパスワードを保存しません。ビルドプロセスで環境変数から設定してください。Google はデバッグキーストアを受け付けません(6.3 Manual、LlamAcademy、GTaXWgKz0e8 [00:06:24])。Development Build はオフにし、最初のアップロード時からシンボルをバンドルに含めます。Play は、シンボルが届く前に受信したクラッシュをシンボリケートしません(6.3 Manual)。設定ではなく、ビルド済みのバンドルを確認してください。
- Android のメインスレッドとスプラッシュ画面は、同じ予算を共有します。 ゲームの ANR の大半はバックグラウンド移行中に発生します。
OnApplicationPauseでは重い処理を行わず、SDK の初期化はマイルストーン達成後に段階的に行い、シンボルを同梱します。スタックトレース、次回起動時の前回終了理由を確認し、ANR の大半を占める低収益デバイスを除外します(Unity Android team、pezwIhA0e04 [00:27:24]、[00:25:12]、[00:13:13]、[00:41:40]、[00:29:02])。Resources インデックスと最初のシーンのAwakeは、スプラッシュ画面の表示中に実行されます(j4YAY36xjwE [00:33:59])。ローダーシーンではCallReportFullyDrawnを使って、実際に操作可能になったフレームを報告します(6.3 Manual)。 - 課金コードは冪等にします。 検証して付与し、その後
ConfirmPurchaseを呼び出します。処理中および永続化された取引 ID で重複を排除します。OnPurchasesFetchedからの保留中の注文も、同じ経路で処理します。確認時にFailedOrderが発生した場合は、保持している注文で再試行し、再付与はしません。取得済みのProductオブジェクトのみを購入します。Google から空の取得結果が返っても、購入を取り消してはいけません。ストアのローカライズされた価格を表示し、jwsRepresentationをアトリビューション SDK に渡します(IAP 5 docs;Unity、szS2KMxZsl4 [00:07:27]、[00:09:28]、[00:11:38])。コールバックの順序にかかわらず、OnAdRewardedでリワード広告の報酬を付与します。 - タッチはイベントと仮想デバイスで扱い、HUD は1つのセーフエリアパネル内に配置します。 EnhancedTouch を使い、Update で
Touchscreen.currentを使うのは避けます。画面上のコントロールは仮想 Gamepad を出力します。親指で操作するコントロールは Constant Physical Size に設定します(Input System team、ptvjumIHxYg [00:20:29])。movementRangeは半径です(観察結果)。セーフエリア外にも描画し、HUD はSafeAreaFitterパネル内に配置します(Chema Damak、PLQ4ywB13eg [00:10:53])。UI Toolkit では top =Screen.height - safeArea.yMaxです(テストで実証済み)。Device Simulator は1本の指しか使えず、パフォーマンスを測定できません。また、UNITY_IOSやネイティブプラグインも使用できません(6.3 docs)。 - SDK とストアは契約事項です。 最初の広告リクエストより前に同意を取得し、最初のマイルストーン達成後に広告 SDK を初期化し、最初の10~15分間は収益化せず、プレイヤーが行き詰まったときにオファーを提示します(Creauctopus、ILv7GzDgteQ [00:01:58]、[00:09:00])。iOS では SKAdNetworkItems と各 SDK のプライバシーマニフェストを設定し、API 33 以降では AD_ID を設定します(LevelPlay docs;6.3 Manual)。トラッキングを行う場合は ATT の説明文を設定します[追加]。Data safety は SDK ベンダーのガイドをもとに回答します。IAP 製品を作成する前に、内部テストトラックへ1回アップロードします(GTaXWgKz0e8 [00:09:06];UXl_C3ZnRLc [00:02:28])。6000.3.21f1 では IAP 4.15.1 と LevelPlay 8.10.1 がデフォルトです。まず 5.4.3 と 9.5.1 に固定してください。
最初に確定すること
ストア(Play には AAB が必要です)、最小仕様のデバイス一覧(GPU ファミリーによって ASTC と ETC2 のどちらを使うかが決まります)、ティアごとの目標 FPS、ダウンロード容量の予算、向き、広告ネットワーク、アプリ内課金(IAP)商品、同意に関する規制(GDPR、CCPA、児童向け)とバックエンドでレシートを検証するかどうか、署名用データ(キーストアのパスと環境変数名、Apple チーム ID:これらは人間が管理します)、スマートフォンが接続されているかどうか(ここでは接続なしのため、デバイスでの手順は引き継ぎになります)。デフォルト:Mobile_High は 60 fps、Mobile_Low は 30 fps(Low を出荷し、ディレクターが昇格させます)、ASTC 6x6、最小 API 25、ターゲット API 36、iOS 15、IL2CPP ARM64、Vulkan の後に OpenGLES3、最初は Minimal ストリッピングです。
ワークフロー
- ベースライン。
MobileTiers.AuditRendering、MobileBuild.AuditPlayerSettings、MobileTextures.AuditTextures、MobileAudio.AuditAudio、MobileStartup.AuditStartup、ut_mobile.code_scan(P)、ut_mobile.package_check(P)をすべてbuild_target="Android"で実行します。GATE: 検出事項を一覧表示し、Editor の Quality レベルを記録します。 - ティアと熱。
MobileTiers.ApplyTiersを実行し、PlayMode の合成FeedイベントでMobileTierDirectorを動作させます。GATE:AuditRenderingのエラーが 0 件、ティアごとのキャプチャを開き、熱テストで lodBias と(GPU がボトルネックの場合のみ)レンダースケールを下げ、両方を元に戻します。 - アセット。
FixTextures、FixAudio、AuditMeshesを実行し、続いてターゲットごとにImportedFormatsとImportedAudioを実行します。MobileImportRulesにはimport_rules.jsonを使います。GATE: エラーと警告が 0 件、すべて ASTC、インポート後のサイズが縮小し、新しいアセットが準拠した状態で取り込まれることを確認します。Max Size を下げる前後のキャプチャを取得します。 - 入力と UI。
SafeAreaFitter、BuildTouchHud、FloatingTouchStickを実行します。GATE:SafeAreaTestsとTouchInputTestsが合格し、CaptureSafeAreaでフィット済み HUD は見やすく、未調整の HUD は遮られていることを確認します。 - フレーム予算。 ティアごとに
AgentProfile.PlayModeTimingsを実行し、budget_verdict(csv, fps)を使います。DeviceSoakLoggerを開発ビルドに組み込みます。GATE:継続実行の判定が合格し、デバイスでの長時間テストは Assumed として一覧表示されます。 - 収益化。 パッケージのバージョンを固定し、ロジックを
PurchaseLedger、RewardGate、AdPacing、AdsInitGateに実装します。アダプターにはIap5Store(validate、price、jws)とLevelPlayAds(初期化前にプライバシーフラグを設定)を使います。GATE:MonetizationTestsが合格し、アダプターが固定したパッケージを参照してコンパイルでき、code_scanとpackage_checkに問題がないことを確認します。 - Android リリース。
make_keystoreを実行し、env=keystore_env(ks)を指定してMobileBuild.BuildAndroidを実行します。GATE:Succeeded、aab_findingsのエラーが 0 件(デバッグ不可、16 KB ページ、シンボル、広告がある場合は AD_ID)、bundletool_sizesが予算内であることを確認します。超過する場合は、サイズ別の Build Report を確認してから Play Asset Delivery を使います。パスワードは保存しません。 - iOS リリース。
Assets/Pluginsにプライバシーマニフェストを配置し、BuildIos、xcode_facts、xcode_findingsを実行します。GATE:Succeeded、理由が引き継がれ、ターゲット GUID が報告されることを確認します。ios_archive_planのコマンド(アーカイブ、App Store 書き出し、シンニングレポート)を人間に提示し、承認が得られた場合のみ実行します。 - デバイスとストアへの引き継ぎ。
soak_verdictで Soak CSV を判定し、ネイティブ GPU プロファイラー、ANR のトリアージとExitInfoを含む Android vitals、サンドボックスでの購入と復元、LevelPlay テストスイートの実行後に削除、Play Console と App Store Connect の手順(手順書 M13)を確認します。
数値
| 値 | 対象 | 出典 |
|---|---|---|
| 16.67 / 10.83 ms、33.33 / 21.67 ms | 60 fps および 30 fps での未調整/持続時(65%)予算 | e-book |
| 10〜15 分;20〜30 分 | デバイスキャプチャ間のクールダウン;負荷テストの時間 | e-book;[追加] |
| 最大 1 ms の CPU | ローエンドモバイルで有効にしたカメラ 1 台あたり | e-book |
| 8〜0.89 bpp | ASTC 4x4〜12x12 | 6.3 Manual |
| < 200 KB / > 350〜400 KB;22,050 Hz | オーディオの負荷タイプ区分;モバイル SFX のサンプルレート上限 | e-book |
| 200 MB / 100 MB | Play での AAB ベースモジュール/APK;iOS のモバイル通信ダウンロード制限(200)も | 6.3 Manual |
| 16 KB(p_align 0x4000) | すべてのネイティブライブラリの LOAD セグメント、Android 15 以降のページ | version deltas |
| API 25 / 36 | 6.3 の最低要件/2026-08-31 以降の Play のターゲット(6.5 では最低要件が 26 に引き上げ) | version deltas |
| iOS 15、A8;Xcode 26 + iOS 26 SDK | 6.3 の最低要件;2026-04-28 以降の App Store | version deltas |
| 5 秒(一部の Samsung では 10 秒);128 バイト | ANR タイムアウト;終了状態の概要 | pezwIhA0e04 [00:02:01]、[00:42:13] |
| 3 日 | Google が未確認の購入を払い戻すまでの期間 | IAP 5 docs |
| 10〜15 分;3 分ごと | マネタイズなしで開始;マイルストーン後のインタースティシャル表示間隔 | ILv7GzDgteQ(ヒューリスティック) |
| 54998〜55511 | iOS のリモートプロファイリング用アウトバウンドポート | 6.3 Manual |
| 0.125〜0.925 | 画面上のスティック値に適用される Gamepad のデフォルトのスティックデッドゾーン | observed |
品質ゲート
- 測定可能: すべての監査でエラーが 0 件(警告には正当な理由があること);
ImportedFormatsがすべて ASTC;NUnit (SafeAreaTests、TouchInputTests、MonetizationTests、TierDirectorTests)の失敗数が 0;budget_verdictが持続時の合格;aab_findingsとxcode_findingsのエラーが 0 件;bundletool_sizesが 予算内;code_scanとpackage_checkのエラーが 0 件;デバイス上で、20 分以上のsoak_verdictが合格。 - ビジュアル: ティアとセーフエリアのキャプチャが
image_checksに合格し、実際に開いて確認済み;Max Size を下げるたびに変更前後のぼかしを確認。
よくある間違い
| 間違い | どのような問題が起きるか | 修正方法 |
|---|---|---|
| Editor で 16.7 ms を基準にプロファイリングする | Mac では問題なくても、スマートフォンでは 10 分後にフレームレートが低下する | 予算を 65% に設定し、デバイスで長時間テストして p95/最大値を確認する |
| モバイルターゲットに PC の Quality レベルを使う | キャプチャで PC_RPAsset が使われる、または PC レベルが含まれて出荷される | ApplyTiers(PC を除外)、SetEditorQuality |
| CPU バウンドのゲームで解像度によるサーマル対策を行う | 画像がぼやけるだけで、ほとんど高速化しない | GPU バウンド時のみレンダースケールを使用し、lodBias とシャドウを調整する |
| RGBA32 への上書き、または ASTC HDR を使わない HDR マップ | 1024 px で 5.3 MB、HDR が ETC2_RGBA8 としてインポートされる | FixTextures、ImportedFormats を確認する |
| 小さなクリップをストリーミングし、音楽を Decompress On Load にする | ストリームごとに 200 KB のオーバーヘッドが発生し、PCM 全体がメモリに読み込まれる | FixAudio(サイズ別に分類) |
| GUI でキーストアを一度だけ設定する | 次のバッチビルドが失敗する、またはデバッグ署名のまま出荷される | BuildAndroid が読み込む環境変数を使う |
| Development Build をアップロードし、シンボルを後からアップロードする | アップロードに失敗し、初期のクラッシュをシンボリケートできない | aab_findings を使い、最初のバンドルにシンボルを含める |
IPostGenerateGradleAndroidProject で Gradle を編集する | インクリメンタルビルドで古い出力が残る | AndroidProjectFilesModifier(カスタムモジュール)を使うか、クリーンビルドを行う |
OnApplicationPause で保存し、最初の Awake で SDK を初期化する | 一時停止時に ANR が発生し、スプラッシュ画面の下で起動が遅くなる | チェックポイントを使い、SDK 初期化を分散し、AuditStartup を実行する |
| IAP 5 で IAP 4 のコードを使い、LevelPlay 8 のフォルダーを残す | コンパイルエラーが発生し、9.x パッケージの隣に 9 未満の SDK ファイルが残る | パッケージのバージョンを固定し、package_check を実行する |
OnPurchaseConfirmed を成功として扱う | FailedOrder が通知されずに失われる | 保持している PendingOrder を使って再試行する |
| IAP 5 の後、アトリビューション SDK が機能しなくなる | iOS の収益が記録されないが、エラーも表示されない | OnAppleJws を使い、その後デバイスで購入を行う |
OnAdClosed でリワードを付与し、テストスイートを残したままにする | リワードが付与されず、リリース版で検証呼び出しが実行される | RewardGate と code_scan を使う |
| HUD をキャンバスにアンカーし、Simulator を証明として扱う | ボタンがノッチの下に配置され、マルチタッチも未テストのままになる | SafeAreaFitter を使い、デバイスで確認する |
| Gamepad が接続されたときに HUD を非表示にする | HUD が自分自身を非表示にする。画面上のコントロールが仮想 Gamepad を追加するため | TouchControlsVisibility(OnScreen usage は除外)を使う |
| プライバシーカテゴリを宣言する | Unity がそのカテゴリに対して示す理由が削除される(0A2A.1、確認済み) | write_privacy_manifest で和集合を維持する |
Android のサイズとして BuildReport.summary.totalSize を使う | 53.9 MB の AAB が 789.8 MB と表示される(確認済み) | aab_facts と bundletool get-size total を使う |
引き継ぎ
- 受け取るもの: scenario-unity-expert からシーン、プレハブ、予算を受け取ります。scenario-unity-ui から UI レイアウト(セーフエリアパネルとタッチ HUD を適用)を受け取ります。scenario-unity-shaders からシェーダー(バリアント、深度/不透明テクスチャの使用方法)を受け取ります。scenario-unity-world-building と scenario-textures からコンテンツ(インポートポリシー)を受け取ります。
- 引き渡すもの: ティアアセットと URP の調査結果を scenario-unity-rendering-lighting に引き渡します。プロファイリング CSV とデバイスキャプチャの依頼を scenario-unity-performance に引き渡します。ビルドジョブ、キーストア、環境変数の規約を scenario-unity-pipeline-automation(CI)に引き渡します。入力バインディングを scenario-unity-architecture に引き渡します。Web サイズやブラウザーに関する作業を scenario-unity-web に引き渡します。パケットには、監査 JSON、コンタクトシート、
aab_factsとゲート、xcode_factsとゲート、NUnit の合計、Verified と Assumed のリスト、デバイスおよびストアのチェックリストを含めます。
Unity 6.3 に関する注意事項
- 2026-08-31 以降、Play のターゲット API は 36 です。最小 API は 25(6.5 では 26)、6000.3.17f1 以降では Gradle 9.1.0/AGP 9.0.0 です。GameActivity がデフォルトのエントリーポイントです。6000.3.21f1 の URP テンプレートでは、Target API Automatic、APK 出力、プレースホルダーのパッケージ ID が設定されています(確認済み)。この 3 つはすべて設定してください。エンジンライブラリは 16 KB にアラインされています(確認済み)。
AndroidProjectFilesModifierが編集するのはカスタムモジュールのみです。AndroidProjectFiles.UnityLibraryManifestは 6000.3.21f1 ではコンパイルされません(確認済み)。LevelPlay 9.5.1 は独自の生成後フックで AD_ID を追加します(ソースで確認済み)。この設定を変更した後は、クリーンビルドを実行してください。QualitySettings.SetQualityLevelの呼び出し後も、そのフレームではGraphicsSettings.currentRenderPipelineが以前のアセットを返しました(確認済み)。QualitySettings.renderPipelineを参照してください。- App Store には Xcode 26 と iOS 26 SDK が必要です。6.4 ではランタイムライブラリが
UnityRuntime.frameworkに移動するため、ポストプロセススクリプトを再確認してください。PVRTC は 6.4 で削除されています。 - Adaptive Performance はコア機能です(
UnityEngine.AdaptivePerformance)。自動制御は Android プロバイダーでのみ利用できます。 LevelPlay.SetConsentは 9.5.1 で非推奨です(LevelPlayPrivacySettings)。com.unity.adsは 2026-01-31 以降、収益化向けのレガシー機能です。
参考資料
references/expert-notes.md:情報源ごとの原則、タイムスタンプ、確認事項、情報源間で見解が異なる箇所。references/procedures.md:そのままコピーして使える M1 から M13 の呼び出し。各項目に実機テストと記録済みの結果を記載しています。references/critique.md:予算、ティア、アセット、UI、ビルド、金銭関連コード、引き継ぎを評価するための基準。references/gui-paths.md:Unity、Xcode、ストアのコンソールを使った同じタスクの手順。references/sources.md:認証情報、URL、最適なタイムスタンプ、改訂履歴を含むすべての情報源。