mcpField
S
scenario-unity-mobile

scenario-unity-mobile

github.com/scenario-labs开发1.2k248 次安装1 天前更新
代码仓库

关于 scenario-unity-mobile

面向 Unity 移动游戏开发者的技能,覆盖性能、资源导入、输入界面、变现逻辑和商店发布。它以持续运行表现和实际构建产物为验证重点,并提供 Android 与 iOS 的审查及发布流程。

主要功能

  1. 01评估持续帧率与热管理
  2. 02审核移动端渲染和资源格式
  3. 03构建触控输入与安全区界面
  4. 04处理内购、广告及隐私流程
  5. 05检查 Android 与 iOS 发布产物

适用场景

  1. 01为低端手机设定并验证帧预算
  2. 02调整纹理、音频和渲染设置
  3. 03测试安全区布局与触控控制
  4. 04检查购买、奖励和广告回调逻辑

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/scenario-labs/skills --skill scenario-unity-mobile

安装后在 Claude Code 中输入/scenario-unity-mobile确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
critique.md
expert-notes.md
gui-paths.md
procedures.md
sources.md
scripts/
ut_mobile.py
scripts/AgentKit/Mobile/
MobileAudio.cs
MobileBuild.cs
MobileImportRules.cs
MobileStartup.cs
MobileTextures.cs
MobileTiers.cs
MobileUi.cs
MobileXcodePostprocess.cs
scripts/Runtime/
AgentKit.Mobile.Runtime.asmdef
AndroidDiagnostics.cs
DeviceSoakLogger.cs
MobileTierPolicy.cs
Monetization.cs
SafeAreaFitter.cs
SafeAreaMath.cs
TouchStick.cs
scripts/Runtime/Iap5/
AgentKit.Mobile.Iap5.asmdef
Iap5Store.cs
scripts/Runtime/LevelPlay9/
AgentKit.Mobile.LevelPlay9.asmdef
LevelPlayAds.cs

详细介绍

Unity 移动端(移动端专家)

专业的移动端开发,意味着游戏在一台使用三年的手机上运行 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/。

原则(专家补充)

  1. 规划持续帧预算,而非峰值预算。 约占 1000/fps 的 65%(60 fps 时为 10.8 ms,30 fps 时为 21.7 ms);在最低端手机上以 p95 和最大值为依据,进行短时突发测试,并冷却 10 到 15 分钟;假设启用了 vsync,因此错过一次刷新就会使帧率减半(Unity 移动端电子书)。设备过热时,只有在 GPU 是瓶颈的情况下才优先降低渲染缩放:分辨率几乎无法改善 CPU 受限的帧(6.3 Manual)。通过合成热事件证明策略,而不是让手机过热(d5O4Uw6gPBI [00:04:21])。编辑器中的耗时数据仅供参考;绘制次数和 SetPass 次数才是稳定的编辑器证据(已观察到)。
  2. 检查实际格式,然后锁定规则。 如果 GPU 无法采样某种纹理,就会在 CPU 上将其解压为 RGBA32(6.3 Manual);未设置 ASTC HDR 覆盖的 HDR 贴图导入后会变为 ETC2_RGBA8(已观察到)。UI 和人脸使用 ASTC 4x4,默认使用 6x6,大型环境贴图使用 8x8 [已添加];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 位;关闭软阴影;Store Actions 设为 Auto 或 Discard(6.3 Manual)。每个 Quality 层级使用一个 URP 资源;为 Android 启动的批处理编辑器仍报告 Quality 为“PC”(已观察到;2J0kDtUGlrY [frame 00:10:28] 中也出现了相同陷阱)。
  4. 发布构建应可根据环境复现。 Unity 从不保存密钥库密码:在构建过程中通过环境变量设置;Google 不接受调试密钥库(6.3 Manual;LlamAcademy,GTaXWgKz0e8 [00:06:24])。关闭 Development Build;从首次上传起就将符号文件包含在包中:对于符号文件上传前收到的崩溃,Play 永远不会进行符号化处理(6.3 Manual)。检查构建完成的包,而非设置。
  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;通过交易 ID 对进行中和已持久化的交易去重;来自 OnPurchasesFetched 的待处理订单也走相同流程;确认时出现 FailedOrder,则使用保留的订单重试,绝不再次发放;只购买已获取的 Product 对象;Google 返回空结果时绝不撤销购买;显示商店本地化价格;将 jwsRepresentation 交给归因 SDK(IAP 5 docs;Unity,szS2KMxZsl4 [00:07:27]、[00:09:28]、[00:11:38])。无论回调顺序如何,都在 OnAdRewarded 中发放奖励广告奖励。
  7. 触控由事件和虚拟设备处理;HUD 位于单一安全区域面板中。 使用 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 只支持一根手指,不提供性能数据,不定义 UNITY_IOS,也不支持原生插件(6.3 docs)。
  8. 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 文本 [已添加];依据 SDK 供应商的指南填写 Data safety;创建 IAP 商品前,先上传到一个内部测试轨道(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);各档位的目标帧率;下载预算;屏幕方向;广告网络、IAP 商品、同意法规(GDPR、CCPA、面向儿童)以及后端是否验证收据;签名材料(keystore 路径和环境变量名称、Apple 团队 ID:由人工保管);是否连接了手机(此处没有:设备步骤改为交接)。默认值:Mobile_High 为 60 fps,Mobile_Low 为 30 fps(发布 Low,由总监决定是否升级);ASTC 6x6;最低 API 25;目标 API 36;iOS 15;IL2CPP ARM64;先用 Vulkan,再用 OpenGLES3;初始采用 Minimal 剥离。

工作流

  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. 档位和热状态。 MobileTiers.ApplyTiers;通过 PlayMode 合成 Feed 事件运行 MobileTierDirector。门槛:AuditRendering 错误数为 0;打开各档位的 捕获结果;热测试降低 lodBias 和(仅 GPU 瓶颈时)渲染比例,并恢复二者。
  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. 帧预算。 按档位运行 AgentProfile.PlayModeTimings、budget_verdict(csv, fps); 将 DeviceSoakLogger 加入开发版本。门槛:持续运行判定通过;设备浸泡测试列为假设项。
  6. 变现。 固定软件包版本;逻辑放在 PurchaseLedger、RewardGate、AdPacing、 AdsInitGate 中;适配器包括 Iap5Store(验证、价格、jws)和 LevelPlayAds(初始化前设置隐私标记)。门槛: MonetizationTests 通过;适配器可针对固定的软件包版本编译;code_scan 和 package_check 无问题。
  7. Android 发布。 运行 make_keystore,通过 MobileBuild.BuildAndroid 构建,并设置 env=keystore_env(ks)。门槛:构建成功;aab_findings 错误数为 0(不可调试、16 KB 页、 符号、投放广告时的 AD_ID);bundletool_sizes 未超出预算,否则按体积查看 Build Report, 然后使用 Play Asset Delivery;不持久化密码。
  8. iOS 发布。 在 Assets/Plugins 中放置隐私清单,运行 BuildIos、xcode_facts + xcode_findings。门槛:构建成功,保留原因,并报告目标 GUID;向人工展示 ios_archive_plan 命令(归档、导出到 App Store、瘦身报告),仅在获批后运行。
  9. 设备和商店交接。 使用 soak_verdict 判定浸泡测试 CSV,使用原生 GPU 性能分析器;检查 Android vitals,进行 ANR 分流并查看 ExitInfo;测试沙盒购买和恢复;先运行 LevelPlay 测试套件,再移除;执行 Play Console 和 App Store Connect 步骤(流程 M13)。

数值

数值相关说明来源
16.67 / 10.83 ms,33.33 / 21.67 ms60 和 30 fps 下的原始 / 持续(65%)预算电子书
10 到 15 min;20 到 30 min设备采集之间的冷却时间;浸泡时长电子书;[已添加]
最多 1 ms CPU低端移动设备上每个启用的摄像头电子书
8 到 0.89 bppASTC 4x4 到 12x126.3 Manual
< 200 KB / > 350 到 400 KB;22,050 Hz音频负载类型分类;移动设备 SFX 采样率上限电子书
200 MB / 100 MBPlay 上的 AAB 基础模块 / APK;也是 iOS 蜂窝网络下载限制(200)6.3 Manual
16 KB(p_align 0x4000)Android 15+ 页面中每个原生库的 LOAD 段版本差异
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 s(部分 Samsung 设备上为 10 s);128 bytesANR 超时;退出状态摘要pezwIhA0e04 [00:02:01],[00:42:13]
3 天Google 会退还未确认的购买IAP 5 docs
10 到 15 min;每 3 min免变现启动时长;里程碑后的插屏间隔ILv7GzDgteQ(启发式规则)
54998 到 55511iOS 远程性能分析的出站端口6.3 Manual
0.125 到 0.925应用于屏幕摇杆值的默认 Gamepad 摇杆死区观察所得

质量门槛

  • 可测量: 每项审核均为 0 个错误(警告须有合理说明);ImportedFormats 全部为 ASTC;NUnit (SafeAreaTests、TouchInputTests、MonetizationTests、TierDirectorTests)失败数 == 0; budget_verdict 持续通过;aab_findings 和 xcode_findings 错误数为 0;bundletool_sizes 符合预算;code_scan 和 package_check 错误数为 0;在设备上,soak_verdict 至少通过 20 分钟。
  • 视觉: 档位和安全区域的截图通过 image_checks 并已打开;每次降低 Max Size 后均检查模糊前后的效果。

常见错误

错误表现修复
在 Editor 中按 16.7 ms 进行性能分析在 Mac 上运行正常,但在手机上运行 10 分钟后便开始降频预算按 65% 计算,进行设备长时间测试,关注 p95/最大值
在移动端目标上使用 PC 质量级别捕获结果使用 PC_RPAsset,或发布了 PC 级别使用 ApplyTiers(排除 PC)和 SetEditorQuality
对 CPU 受限的游戏通过分辨率应对温度升高画面变模糊,速度却几乎没有提升仅在受 GPU 限制时调整渲染比例;调整 lodBias、阴影
覆盖为 RGBA32;HDR 地图未使用 ASTC HDR1024 px 纹理占用 5.3 MB;HDR 被导入为 ETC2_RGBA8使用 FixTextures,检查 ImportedFormats
流式传输较小的片段;音乐使用 Decompress On Load每个流多出 200 KB 开销;完整 PCM 驻留在内存中使用 FixAudio(按大小分桶)
只在 GUI 中设置一次密钥库下一次批量构建失败,或发布了使用调试签名的版本BuildAndroid 读取环境变量
上传 Development Build;延后上传符号上传失败;早期崩溃记录从未进行符号化使用 aab_findings;在第一个 bundle 中包含符号
在 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 连接时隐藏 HUDHUD 把自己隐藏了:其屏幕控件会添加一个虚拟 Gamepad使用 TouchControlsVisibility(跳过 OnScreen 用法)
声明隐私类别Unity 为其提供的理由被丢弃(0A2A.1,已观察到)write_privacy_manifest 会保留并集
将 BuildReport.summary.totalSize 作为 Android 大小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 总数、已验证和假设事项列表、设备与商店检查清单。

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(观察所得):请设置这三项。引擎库已按 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);自 2026-01-31 起,com.unity.ads 已属于旧版变现方案。

参考资料

评论

支持 Markdown