scenario-unity-mobile

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Unity mobile (mobile specialist)

Unity 移动端(移动端专家)

Expert mobile work means a game that holds its frame rate after twenty minutes on a three-year-old phone, starts fast, installs from the store, and never double-charges or double-grants. The stance: budget the sustained frame, prove every setting on the data the device gets (imported format, built bundle, exported Xcode project), and treat stores, SDKs and money code as contracts with ugly event orders. Target: Unity 6000.3.21f1, URP 17.3, Input System 1.20, macOS with Xcode 26.6. If a sibling skill named here is missing from your available skills, ask the user to install it (
npx skills add scenario-labs/skills --skill <name>
); unattended, proceed from tool schemas and flag the gap.
REQUIRED BACKGROUND: scenario-unity-expert (channels, review loop, 6.3 traps). Toolkit:
scripts/ut_mobile.py
(imports
ut_env
,
ut_run
,
ut_stat
), editor jobs in
scripts/AgentKit/Mobile/
, player code in
scripts/Runtime/
.
专业的移动端工作意味着:游戏在一台三年前的手机上运行 20 分钟后仍能保持帧率,启动快捷,能够从商店完成安装,而且绝不会重复扣款或重复发放权益。其原则是:为持续帧率设定预算,基于设备实际获得的数据(导入格式、构建后的 bundle、导出的 Xcode 项目)验证每一项设置,并将商店、SDK 和支付代码视为契约,同时妥善处理其混乱的事件顺序。目标环境:Unity 6000.3.21f1、URP 17.3、Input System 1.20、macOS 与 Xcode 26.6。如果这里提到的某个同级 skill 不在你可用的 skills 中,请要求用户安装(
npx skills add scenario-labs/skills --skill <name>
);在无人值守的情况下,依据工具 schema 继续执行,并标记该缺口。
必需背景: scenario-unity-expert(
channels
、review loop、6.3 陷阱)。工具包:
scripts/ut_mobile.py
(导入
ut_env
、
ut_run
、
ut_stat
),Editor 作业位于
scripts/AgentKit/Mobile/
,Player 代码位于
scripts/Runtime/
。

Stance (the expert delta)

原则(专家侧重点)

  1. Budget the sustained frame, not the peak. About 65% of 1000/fps (10.8 ms at 60, 21.7 ms at 30), judged on p95 and max, on the lowest phone, short bursts, 10 to 15 minutes of cooldown; assume vsync, so a missed refresh halves the rate (Unity mobile e-book). Under heat, lower render scale first only when the GPU is the bottleneck: resolution barely helps a CPU-bound frame (6.3 Manual). Prove the policy with synthetic thermal events, not a hot phone (d5O4Uw6gPBI [00:04:21]). Editor timings are relative; draw and SetPass counts are the stable Editor evidence (observed).
  2. Check the effective format, then lock the rule. A texture the GPU cannot sample is decompressed to RGBA32 on the CPU (6.3 Manual); an HDR map without an ASTC HDR override imported as ETC2_RGBA8 (observed). ASTC 4x4 UI and faces, 6x6 default, 8x8 big environment maps [added]; crunch does nothing on ASTC. Audio: WAV sources, mono SFX at 22,050 Hz at most, ADPCM under 200 KB, Streaming only above about 400 KB (e-book). An
    AssetPostprocessor
    keeps new assets compliant (Unity Enterprise Support, j4YAY36xjwE [00:19:07]).
  3. Mobile URP is not PC URP with a lower slider. Depth Priming Disabled (unsupported on Android, iOS and TBDR), Native RenderPass on, Depth and Opaque textures off unless sampled, HDR off or 32-bit, soft shadows off, Store Actions Auto or Discard (6.3 Manual). One URP asset per Quality tier; a batch editor launched for Android still reported Quality "PC" (observed; same trap in 2J0kDtUGlrY [frame 00:10:28]).
  4. Release builds are reproducible from the environment. Unity never stores keystore passwords: set them in the build process from env vars; Google refuses the debug keystore (6.3 Manual; LlamAcademy, GTaXWgKz0e8 [00:06:24]). Development Build off, symbols in the bundle from the first upload: Play never symbolicates crashes received before the symbols (6.3 Manual). Check the built bundle, not the settings.
  5. The Android main thread and the splash are shared budgets. Most game ANRs happen while backgrounding: nothing heavy in
    OnApplicationPause
    , SDK init staggered after milestones, symbols shipped; read the signature, the previous exit reason on next launch, and exclude low-revenue devices that dominate ANRs (Unity Android team, pezwIhA0e04 [00:27:24], [00:25:12], [00:13:13], [00:41:40], [00:29:02]). The Resources index and first-scene
    Awake
    run under the splash (j4YAY36xjwE [00:33:59]); a loader scene reports its real interactive frame with
    CallReportFullyDrawn
    (6.3 Manual).
  6. Money code is idempotent. Validate, grant, then
    ConfirmPurchase
    ; dedupe by transaction id in flight and persisted; pending orders from
    OnPurchasesFetched
    go through the same path; a
    FailedOrder
    on confirm is retried with the kept order, never regranted; buy only fetched
    Product
    objects; never revoke on an empty Google fetch; show the store's localized price; hand
    jwsRepresentation
    to attribution SDKs (IAP 5 docs; Unity, szS2KMxZsl4 [00:07:27], [00:09:28], [00:11:38]). Grant rewarded ads in
    OnAdRewarded
    whatever the callback order.
  7. Touch is events and virtual devices; the HUD lives in one safe-area panel. EnhancedTouch, never
    Touchscreen.current
    in Update; on-screen controls emit a virtual Gamepad; thumb controls at Constant Physical Size (Input System team, ptvjumIHxYg [00:20:29]).
    movementRange
    is a radius (observed). Render outside the safe area on, HUD in a
    SafeAreaFitter
    panel (Chema Damak, PLQ4ywB13eg [00:10:53]); UI Toolkit top =
    Screen.height - safeArea.yMax
    (proven by test). The Device Simulator is one finger, no performance, no
    UNITY_IOS
    , no native plug-ins (6.3 docs).
  8. SDKs and stores are contracts. Consent answered before the first ad request, ad SDK init after the first milestone, nothing monetized in the first 10 to 15 minutes, offers when the player is stuck (Creauctopus, ILv7GzDgteQ [00:01:58], [00:09:00]); SKAdNetworkItems and every SDK's privacy manifest on iOS, AD_ID on API 33+ (LevelPlay docs; 6.3 Manual), the ATT text when you track [added]; Data safety answered from the SDK vendors' guides; one internal-track upload before IAP products can exist (GTaXWgKz0e8 [00:09:06]; UXl_C3ZnRLc [00:02:28]). 6000.3.21f1 defaults to IAP 4.15.1 and LevelPlay 8.10.1: pin 5.4.3 and 9.5.1 first.
  1. 为持续帧率做预算,而不是只关注峰值。 预算约为 1000/fps 的 65%(60 fps 时为 10.8 ms,30 fps 时为 21.7 ms),依据最低配置手机上的 p95 和 max 判定,并覆盖短时突发负载以及 10 到 15 分钟的冷却期;假定启用了 vsync,因此错过一次刷新会让帧率减半(Unity 移动端电子书)。发生热衰减时,只有在 GPU 是瓶颈时才优先降低 render scale:对 CPU 受限的帧而言,降低分辨率几乎无助于性能(6.3 Manual)。应使用合成热事件来验证策略,而不是依赖已经发热的手机(d5O4Uw6gPBI [00:04:21])。Editor 中的计时数据是相对值;draw 和 SetPass 计数是稳定的 Editor 证据(实测)。
  2. 先检查实际生效的格式,再锁定规则。 如果 GPU 无法采样某种纹理,它会在 CPU 上被解压为 RGBA32(6.3 Manual);未设置 ASTC HDR override 的 HDR 贴图会以 ETC2_RGBA8 导入(实测)。UI 和面部使用 ASTC 4x4,默认使用 6x6,大型环境贴图使用 8x8 [added];crunch 对 ASTC 不起作用。音频:源文件使用 WAV;单声道 SFX 的采样率最高为 22,050 Hz;小于 200 KB 时使用 ADPCM;仅当文件大于约 400 KB 时才使用 Streaming(电子书)。使用
    AssetPostprocessor
    确保新资源符合规范(Unity Enterprise Support,j4YAY36xjwE [00:19:07])。
  3. 移动端 URP 不是把 PC URP 的参数调低。 将 Depth Priming 设为 Disabled(Android、iOS 和 TBDR 不支持),开启 Native RenderPass,除非会被采样,否则关闭 Depth 和 Opaque 纹理,关闭 HDR 或使用 32-bit,关闭软阴影,将 Store Actions 设为 Auto 或 Discard(6.3 Manual)。每个 Quality tier 使用一个 URP asset;为 Android 启动批处理 Editor 时仍报告 Quality“PC”(实测;2J0kDtUGlrY 中存在同样的陷阱 [frame 00:10:28])。
  4. 发布构建必须能从环境复现。 Unity 不会存储 keystore 密码:应在构建流程中通过环境变量传入;Google 会拒绝 debug keystore(6.3 Manual;LlamAcademy,GTaXWgKz0e8 [00:06:24])。关闭 Development Build,从首次上传起就把符号文件包含在 bundle 中:Play 无法对在符号文件上传之前收到的崩溃进行符号化(6.3 Manual)。应检查构建后的 bundle,而不是仅检查设置。
  5. 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)。
  6. 支付代码必须具备幂等性。 先验证、再发放,然后调用
    ConfirmPurchase
    ;同时对处理中及已持久化的订单按 transaction id 去重;
    OnPurchasesFetched
    返回的 pending order 必须走同一流程;确认时出现
    FailedOrder
    ,应使用保留的订单重试,绝不能再次发放;只能购买已获取到的
    Product
    对象;Google fetch 为空时绝不能撤销购买;显示商店的本地化价格;将
    jwsRepresentation
    交给归因 SDK(IAP 5 文档;Unity,szS2KMxZsl4 [00:07:27]、[00:09:28]、[00:11:38])。无论回调顺序如何,都应在
    OnAdRewarded
    中发放激励广告奖励。
  7. 触控应基于事件和虚拟设备实现;HUD 应集中在一个安全区面板中。 使用 EnhancedTouch,绝不要在 Update 中使用
    Touchscreen.current
    ;屏幕控件应发出虚拟 Gamepad 输入;拇指操作控件采用 Constant Physical Size(Input System 团队,ptvjumIHxYg [00:20:29])。
    movementRange
    是半径(实测)。启用“在安全区外渲染”,将 HUD 放在
    SafeAreaFitter
    面板中(Chema Damak,PLQ4ywB13eg [00:10:53]);UI Toolkit 的 top =
    Screen.height - safeArea.yMax
    (测试已证明)。Device Simulator 仅支持单指,不具备性能测试能力,不提供
    UNITY_IOS
    ,也不支持原生插件(6.3 文档)。
  8. SDK 和商店都是契约。 在首次广告请求之前完成同意处理,在首个里程碑之后再初始化广告 SDK,开局 10 到 15 分钟内不进行任何变现,并在玩家卡住时提供相应选项(Creauctopus,ILv7GzDgteQ [00:01:58]、[00:09:00]);在 iOS 上提供 SKAdNetworkItems 以及每个 SDK 的隐私清单,在 API 33+ 上提供 AD_ID(LevelPlay 文档;6.3 Manual);启用跟踪时展示 ATT 文本 [added];依据 SDK 供应商的指南回答 Data safety 问题;IAP 商品存在之前,先向 internal track 上传一次(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。

Establish first

首先确定

Stores (Play needs an AAB); min-spec device list (GPU family decides ASTC vs ETC2); target fps per tier; download budget; orientation; ad network, IAP products, consent regimes (GDPR, CCPA, child-directed) and whether a backend validates receipts; signing material (keystore path and env var names, Apple team id: the human keeps them); whether a phone is connected (none here: device steps become a hand-over). Defaults: Mobile_High 60 fps and Mobile_Low 30 fps (Low ships, the director promotes), ASTC 6x6, min API 25, target API 36, iOS 15, IL2CPP ARM64, Vulkan then OpenGLES3, Minimal stripping to start.
商店(Play 需要 AAB);最低规格设备清单(GPU 系列决定使用 ASTC 还是 ETC2);每个 tier 的目标 fps;下载预算;屏幕方向;广告网络、IAP 商品、同意制度(GDPR、CCPA、儿童定向广告)以及是否由后端验证收据;签名资料(keystore 路径和环境变量名、Apple team id:由人工负责人保管);当前是否有手机连接(当前无:设备步骤将转为人工交接)。默认值:Mobile_High 为 60 fps,Mobile_Low 为 30 fps(Low 随包发布,由 director 提升),ASTC 6x6,最低 API 25,目标 API 36,iOS 15,IL2CPP ARM64,优先使用 Vulkan,然后是 OpenGLES3,起始阶段采用 Minimal stripping。

Workflow

工作流

  1. Baseline.
    MobileTiers.AuditRendering
    ,
    MobileBuild.AuditPlayerSettings
    ,
    MobileTextures.AuditTextures
    ,
    MobileAudio.AuditAudio
    ,
    MobileStartup.AuditStartup
    ,
    ut_mobile.code_scan(P)
    ,
    ut_mobile.package_check(P)
    , all with
    build_target="Android"
    . GATE: findings listed, Editor Quality level recorded.
  2. Tiers and thermals.
    MobileTiers.ApplyTiers
    ;
    MobileTierDirector
    with PlayMode synthetic
    Feed
    events. GATE:
    AuditRendering
    0 errors; per-tier captures opened; the thermal test lowers lodBias and (GPU-bound only) render scale, restores both.
  3. Assets.
    FixTextures
    ,
    FixAudio
    ,
    AuditMeshes
    , then
    ImportedFormats
    and
    ImportedAudio
    per target;
    import_rules.json
    for
    MobileImportRules
    . GATE: 0 errors and warns, all ASTC, imported sizes down, new assets arrive compliant; captures before and after any Max Size drop.
  4. Input and UI.
    SafeAreaFitter
    ,
    BuildTouchHud
    ,
    FloatingTouchStick
    . GATE:
    SafeAreaTests
    and
    TouchInputTests
    pass;
    CaptureSafeArea
    fitted HUD clear, naive HUD blocked.
  5. Frame budget.
    AgentProfile.PlayModeTimings
    per tier,
    budget_verdict(csv, fps)
    ;
    DeviceSoakLogger
    goes into the development build. GATE: sustained verdict pass; device soak listed as Assumed.
  6. Monetization. Pin packages; logic in
    PurchaseLedger
    ,
    RewardGate
    ,
    AdPacing
    ,
    AdsInitGate
    ; adapters
    Iap5Store
    (validate, price, jws) and
    LevelPlayAds
    (privacy flags before init). GATE:
    MonetizationTests
    pass, adapters compile against the pinned packages,
    code_scan
    and
    package_check
    clean.
  7. Android release.
    make_keystore
    ,
    MobileBuild.BuildAndroid
    with
    env=keystore_env(ks)
    . GATE: Succeeded;
    aab_findings
    0 errors (not debuggable, 16 KB pages, symbols, AD_ID if ads);
    bundletool_sizes
    under budget, else Build Report by size then Play Asset Delivery; passwords not persisted.
  8. iOS release. Privacy manifest in
    Assets/Plugins
    ,
    BuildIos
    ,
    xcode_facts
    +
    xcode_findings
    . GATE: Succeeded, reasons carried, target GUIDs reported;
    ios_archive_plan
    commands (archive, App Store export, thinning report) shown to the human and run only with approval.
  9. Device and store hand-over. Soak CSV judged by
    soak_verdict
    , native GPU profilers, Android vitals with ANR triage and
    ExitInfo
    , sandbox purchase and restore, LevelPlay test suite then removal, Play Console and App Store Connect steps (procedures M13).
  1. 基线。
    MobileTiers.AuditRendering
    、
    MobileBuild.AuditPlayerSettings
    、
    MobileTextures.AuditTextures
    、
    MobileAudio.AuditAudio
    、
    MobileStartup.AuditStartup
    、
    ut_mobile.code_scan(P)
    、
    ut_mobile.package_check(P)
    ,全部使用
    build_target="Android"
    。门禁:列出发现结果,并记录 Editor Quality 级别。
  2. Tier 与热衰减。
    MobileTiers.ApplyTiers
    ;使用 PlayMode 合成
    Feed
    事件驱动
    MobileTierDirector
    。门禁:
    AuditRendering
    为 0 个错误;打开每个 tier 的捕获结果;热衰减测试降低 lodBias,并且仅在 GPU 受限时降低 render scale,随后恢复两者。
  3. 资源。
    FixTextures
    、
    FixAudio
    、
    AuditMeshes
    ,然后针对每个目标执行
    ImportedFormats
    和
    ImportedAudio
    ;为
    MobileImportRules
    准备
    import_rules.json
    。门禁:0 个错误和警告,全部采用 ASTC,导入后体积下降,新资源符合规范;每次降低 Max Size 前后都要保留捕获结果。
  4. 输入与 UI。
    SafeAreaFitter
    、
    BuildTouchHud
    、
    FloatingTouchStick
    。门禁:
    SafeAreaTests
    和
    TouchInputTests
    通过;
    CaptureSafeArea
    显示适配后的 HUD 无遮挡,而朴素 HUD 存在遮挡。
  5. 帧率预算。 对每个 tier 执行
    AgentProfile.PlayModeTimings
    、
    budget_verdict(csv, fps)
    ;将
    DeviceSoakLogger
    加入 development build。门禁:持续性能判定通过;设备浸泡测试列为 Assumed。
  6. 变现。 固定包版本;将逻辑放入
    PurchaseLedger
    、
    RewardGate
    、
    AdPacing
    、
    AdsInitGate
    ;适配器包括
    Iap5Store
    (验证、价格、jws)和
    LevelPlayAds
    (初始化前处理隐私标志)。门禁:
    MonetizationTests
    通过,适配器能够针对固定版本的包进行编译,
    code_scan
    和
    package_check
    无错误。
  7. Android 发布。 执行
    make_keystore
    ,并使用
    env=keystore_env(ks)
    运行
    MobileBuild.BuildAndroid
    。门禁:Succeeded;
    aab_findings
    为 0 个错误(不可调试、16 KB pages、符号文件,以及使用广告时的 AD_ID);
    bundletool_sizes
    在预算内,否则使用 Build Report 按体积排序,再使用 Play Asset Delivery;密码未被持久化。
  8. iOS 发布。 将隐私清单放入
    Assets/Plugins
    ,执行
    BuildIos
    、
    xcode_facts
    和
    xcode_findings
    。门禁:Succeeded,保留 reasons,并报告 target GUID;向负责人展示
    ios_archive_plan
    命令(archive、App Store export、thinning report),仅在获得批准后执行。
  9. 设备与商店交接。 使用
    soak_verdict
    判定浸泡测试 CSV,使用原生 GPU profiler,执行 Android vitals 分析和 ANR 分诊与
    ExitInfo
    ,进行沙盒购买与恢复,运行 LevelPlay 测试套件后将其移除,并执行 Play Console 和 App Store Connect 步骤(procedures M13)。

Numbers

数值

ValueRelative toSource
16.67 / 10.83 ms, 33.33 / 21.67 msraw / sustained (65%) budget at 60 and 30 fpse-book
10 to 15 min; 20 to 30 mincooldown between device captures; soak lengthe-book; [added]
up to 1 ms CPUeach enabled camera on low-end mobilee-book
8 to 0.89 bppASTC 4x4 to 12x126.3 Manual
< 200 KB / > 350 to 400 KB; 22,050 Hzaudio load type buckets; mobile SFX sample rate ceilinge-book
200 MB / 100 MBAAB base module / APK on Play; also the iOS cellular download limit (200)6.3 Manual
16 KB (p_align 0x4000)every native library's LOAD segments, Android 15+ pagesversion deltas
API 25 / 366.3 minimum / Play target since 2026-08-31 (6.5 raises the minimum to 26)version deltas
iOS 15, A8; Xcode 26 + iOS 26 SDK6.3 minimum; App Store since 2026-04-28version deltas
5 s (10 s on some Samsung); 128 bytesANR timeout; exit state summarypezwIhA0e04 [00:02:01], [00:42:13]
3 daysGoogle refunds an unacknowledged purchaseIAP 5 docs
10 to 15 min; every 3 minmonetization-free start; interstitial interval after a milestoneILv7GzDgteQ (heuristics)
54998 to 55511outbound ports for iOS remote profiling6.3 Manual
0.125 to 0.925default Gamepad stick deadzone applied to on-screen stick valuesobserved
数值相对于来源
16.67 / 10.83 ms,33.33 / 21.67 ms60 和 30 fps 下的原始 / 持续(65%)预算电子书
10 到 15 分钟;20 到 30 分钟设备捕获之间的冷却时间;浸泡测试时长电子书;[added]
最多 1 ms CPU低端手机上每个启用的 camera电子书
8 到 0.89 bppASTC 4x4 到 12x126.3 Manual
< 200 KB / > 350 到 400 KB;22,050 Hz音频加载类型分桶;移动端 SFX 采样率上限电子书
200 MB / 100 MBAAB 基础模块 / Play 上的 APK;同时也是 iOS 蜂窝网络下载上限(200)6.3 Manual
16 KB(p_align 0x4000)Android 15+ 页面上每个原生库的 LOAD segments版本差异
API 25 / 366.3 最低要求 / 自 2026-08-31 起的 Play 目标版本(6.5 将最低版本提升至 26)版本差异
iOS 15、A8;Xcode 26 + iOS 26 SDK6.3 最低要求;自 2026-04-28 起的 App Store 要求版本差异
5 秒(部分 Samsung 设备为 10 秒);128 字节ANR 超时;退出状态摘要pezwIhA0e04 [00:02:01]、[00:42:13]
3 天Google 退款尚未确认的购买IAP 5 文档
10 到 15 分钟;每 3 分钟无变现内容的开局时长;首个里程碑之后的插屏广告间隔ILv7GzDgteQ(启发式规则)
54998 到 55511iOS 远程性能分析所需的出站端口6.3 Manual
0.125 到 0.925应用于屏幕摇杆数值的默认 Gamepad 摇杆死区实测

Quality gates

质量门禁

  • Measurable: every audit at 0 errors (warns justified);
    ImportedFormats
    all ASTC; NUnit (
    SafeAreaTests
    ,
    TouchInputTests
    ,
    MonetizationTests
    ,
    TierDirectorTests
    ) failed == 0;
    budget_verdict
    sustained pass;
    aab_findings
    and
    xcode_findings
    0 errors;
    bundletool_sizes
    within budget;
    code_scan
    and
    package_check
    0 errors; on device,
    soak_verdict
    pass over 20 minutes or more.
  • Visual: tier and safe-area captures pass
    image_checks
    and were opened; before/after blur check for every Max Size drop.
  • 可衡量: 每项审计均为 0 个错误(警告均有合理依据);
    ImportedFormats
    全部为 ASTC;NUnit(
    SafeAreaTests
    、
    TouchInputTests
    、
    MonetizationTests
    、
    TierDirectorTests
    )failed == 0;
    budget_verdict
    持续性能判定通过;
    aab_findings
    和
    xcode_findings
    均为 0 个错误;
    bundletool_sizes
    在预算内;
    code_scan
    和
    package_check
    均为 0 个错误;在设备上,
    soak_verdict
    在 20 分钟或更长时间内通过。
  • 视觉: tier 和安全区捕获结果通过
    image_checks
    且已打开检查;每次降低 Max Size 前后都要进行模糊度检查。

Common mistakes

常见错误

MistakeWhat it looks likeFix
profiling against 16.7 ms in the Editorfine on the Mac, throttles after 10 minutes on a phone65% budget, device soak, p95/max
PC Quality level on the mobile targetcaptures use
PC_RPAsset
, or a PC level ships
ApplyTiers
(exclude PC),
SetEditorQuality
thermal response by resolution on a CPU-bound gameblurrier, barely fasterrender scale only when GPU-bound; lodBias, shadows
RGBA32 override; HDR map without ASTC HDR5.3 MB for 1024 px; HDR imported as ETC2_RGBA8
FixTextures
, check
ImportedFormats
streaming small clips; music Decompress On Load200 KB overhead per stream; whole PCM in memory
FixAudio
(buckets by size)
keystore set once in the GUInext batch build fails, or ships debug-signedenv vars read by
BuildAndroid
Development Build uploaded; symbols uploaded lateupload fails; early crashes never symbolicated
aab_findings
; symbols in the first bundle
Gradle edits in
IPostGenerateGradleAndroidProject
stale outputs from incremental builds
AndroidProjectFilesModifier
(custom modules) or a clean build
saves in
OnApplicationPause
; SDKs in the first
Awake
ANRs on pause; slow start under the splashcheckpoints; stagger SDK init;
AuditStartup
IAP 4 code on IAP 5; LevelPlay 8 folders leftcompile errors; pre-9 SDK files beside the 9.x packagepin packages,
package_check
OnPurchaseConfirmed
read as success
a
FailedOrder
silently lost
retry with the kept
PendingOrder
attribution SDK blind after IAP 5iOS revenue missing, no error
OnAppleJws
, then a device purchase
reward granted in
OnAdClosed
; test suite left in
missing rewards; validation calls in release
RewardGate
;
code_scan
HUD anchored to the canvas; Simulator taken as proofbuttons under the notch; multitouch untested
SafeAreaFitter
; device check
hiding the HUD when any Gamepad connectsthe HUD hides itself: its own on-screen controls add a virtual Gamepad
TouchControlsVisibility
(skips the OnScreen usage)
a declared privacy categoryUnity's reasons for it dropped (0A2A.1, observed)
write_privacy_manifest
keeps the union
BuildReport.summary.totalSize
as Android size
789.8 MB for a 53.9 MB AAB (observed)
aab_facts
,
bundletool get-size total
错误表现修复
在 Editor 中以 16.7 ms 为基准做性能分析在 Mac 上表现良好,但在手机上 10 分钟后会降频使用 65% 预算、设备浸泡测试以及 p95/max
移动目标使用 PC Quality level捕获结果使用
PC_RPAsset
,或随包发布 PC level
ApplyTiers
(排除 PC)、
SetEditorQuality
对 CPU 受限游戏采用降低分辨率的热响应画面更模糊,性能几乎没有提升仅在 GPU 受限时降低 render scale;调整 lodBias 和阴影
RGBA32 override;HDR 贴图缺少 ASTC HDR1024 px 下为 5.3 MB;HDR 被导入为 ETC2_RGBA8
FixTextures
,检查
ImportedFormats
对小片段使用 Streaming;音乐使用 Decompress On Load每个 stream 增加 200 KB 开销;完整 PCM 常驻内存
FixAudio
(按大小分桶)
在 GUI 中只设置一次 keystore下一次批处理构建失败,或发布的是 debug 签名版本由
BuildAndroid
读取环境变量
上传 Development Build;符号文件上传过晚上传失败;早期崩溃无法符号化
aab_findings
;首个 bundle 中包含符号文件
在
IPostGenerateGradleAndroidProject
中修改 Gradle
增量构建留下过期输出
AndroidProjectFilesModifier
(自定义模块)或执行干净构建
在
OnApplicationPause
中保存;在首个
Awake
中初始化 SDK
暂停时发生 ANR;在启动画面期间启动缓慢使用存档检查点;错开 SDK 初始化;
AuditStartup
IAP 5 中仍使用 IAP 4 代码;遗留 LevelPlay 8 文件夹编译错误;9.x 包旁残留 pre-9 SDK 文件固定包版本,执行
package_check
将
OnPurchaseConfirmed
视为成功
FailedOrder
被静默丢失
使用保留的
PendingOrder
重试
IAP 5 后归因 SDK 仍处于盲态iOS 收入缺失且没有报错先调用
OnAppleJws
,然后执行设备购买
在
OnAdClosed
中发放奖励;测试套件未移除
奖励未发放;发布版中仍会调用验证接口
RewardGate
;
code_scan
HUD 锚定到 canvas;把 Simulator 当作证明按钮被刘海遮挡;未测试多点触控
SafeAreaFitter
;设备检查
连接任意 Gamepad 时隐藏 HUDHUD 会自行隐藏:其屏幕控件会添加虚拟 Gamepad
TouchControlsVisibility
(跳过 OnScreen usage)
声明了隐私类别Unity 丢弃了对应理由(0A2A.1,实测)
write_privacy_manifest
保留并集
将
BuildReport.summary.totalSize
当作 Android 大小
53.9 MB 的 AAB 却显示为 789.8 MB(实测)
aab_facts
、
bundletool get-size total

Handoffs

交接

  • Receives: scenes, prefabs and budgets from scenario-unity-expert; UI layouts from scenario-unity-ui (applies the safe-area panel and touch HUD); shaders from scenario-unity-shaders (variants, depth/opaque texture use); content from scenario-unity-world-building and scenario-textures (import policy).
  • Delivers: tier assets and URP findings to scenario-unity-rendering-lighting; profiling CSVs and device capture requests to scenario-unity-performance; build jobs, keystore and env conventions to scenario-unity-pipeline-automation (CI); input bindings to scenario-unity-architecture; web size or browser work to scenario-unity-web. Packet: audits JSON, contact sheets,
    aab_facts
    and gates,
    xcode_facts
    and gates, NUnit totals, Verified and Assumed lists, the device and store checklist.
  • 接收: 来自 scenario-unity-expert 的场景、prefab 和预算;来自 scenario-unity-ui 的 UI 布局(应用安全区面板和触控 HUD);来自 scenario-unity-shaders 的 shader(变体、depth/opaque texture 使用);来自 scenario-unity-world-building 和 scenario-textures 的内容(导入策略)。
  • 交付: 向 scenario-unity-rendering-lighting 交付 tier assets 和 URP 发现结果;向 scenario-unity-performance 交付性能分析 CSV 和设备捕获请求;向 scenario-unity-pipeline-automation(CI)交付构建任务、keystore 和环境变量约定;向 scenario-unity-architecture 交付输入绑定;向 scenario-unity-web 交付 Web 体积或浏览器相关工作。交付包:审计 JSON、contact sheets、
    aab_facts
    和门禁、
    xcode_facts
    和门禁、NUnit 总数、Verified 和 Assumed 列表,以及设备与商店检查清单。

Unity 6.3 notes

Unity 6.3 注意事项

  • Target API 36 for Play since 2026-08-31; min API 25 (26 in 6.5); Gradle 9.1.0 / AGP 9.0.0 in 6000.3.17f1+; GameActivity is the default entry point. The 6000.3.21f1 URP template ships Target API Automatic, APK output and a placeholder package id (observed): set all three. Engine libraries are 16 KB aligned (observed).
  • AndroidProjectFilesModifier
    edits custom modules only:
    AndroidProjectFiles.UnityLibraryManifest
    does not compile in 6000.3.21f1 (observed). LevelPlay 9.5.1 adds AD_ID through its own post-generate hook (read in the source): clean-build after changing that setting.
  • After
    QualitySettings.SetQualityLevel
    ,
    GraphicsSettings.currentRenderPipeline
    still returned the previous asset that frame (observed): read
    QualitySettings.renderPipeline
    .
  • App Store needs Xcode 26 and the iOS 26 SDK; 6.4 moves runtime libraries into
    UnityRuntime.framework
    (re-check post-process scripts). PVRTC removed in 6.4.
  • Adaptive Performance is a core feature (
    UnityEngine.AdaptivePerformance
    ); automatic control only with Android providers.
  • LevelPlay.SetConsent
    is obsolete in 9.5.1 (
    LevelPlayPrivacySettings
    );
    com.unity.ads
    is legacy for monetization since 2026-01-31.
  • Play 自 2026-08-31 起要求目标 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 输出和占位 package id(实测):这三项都必须设置。引擎库按 16 KB 对齐(实测)。
  • AndroidProjectFilesModifier
    只能编辑自定义模块:
    AndroidProjectFiles.UnityLibraryManifest
    在 6000.3.21f1 中无法编译(实测)。LevelPlay 9.5.1 通过自己的 post-generate hook 添加 AD_ID(源码中可见):更改该设置后执行干净构建。
  • 调用
    QualitySettings.SetQualityLevel
    后,
    GraphicsSettings.currentRenderPipeline
    在同一帧仍返回上一个 asset(实测):应读取
    QualitySettings.renderPipeline
    。
  • App Store 要求 Xcode 26 和 iOS 26 SDK;6.4 将运行时库移入
    UnityRuntime.framework
    (重新检查 post-process scripts)。PVRTC 在 6.4 中被移除。
  • Adaptive Performance 是核心功能(
    UnityEngine.AdaptivePerformance
    );只有使用 Android provider 时才能自动控制。
  • LevelPlay.SetConsent
    在 9.5.1 中已弃用(
    LevelPlayPrivacySettings
    );自 2026-01-31 起,
    com.unity.ads
    不再用于变现,属于旧版方案。

References

参考资料

  • references/expert-notes.md
    : principles by source with timestamps, observations, and where sources disagree.
  • references/procedures.md
    : M1 to M13 as copyable calls, each with its live test and recorded result.
  • references/critique.md
    : the rubric to judge budgets, tiers, assets, UI, builds, money code and hand-overs.
  • references/gui-paths.md
    : the same tasks through Unity, Xcode and store consoles.
  • references/sources.md
    : every source with credentials, URLs, best timestamps, and the revision history.
  • references/expert-notes.md
    :按来源整理的原则,包含时间戳、实测结果以及来源存在分歧之处。
  • references/procedures.md
    :M1 到 M13 的可复制调用,每个均附现场测试和记录结果。
  • references/critique.md
    :用于评审预算、tier、资源、UI、构建、支付代码和交接工作的评分准则。
  • references/gui-paths.md
    :通过 Unity、Xcode 和商店控制台执行相同任务的路径。
  • references/sources.md
    :每个来源均附访问凭据、URL、最佳时间戳和修订历史。