在iOS使用MetricKit收集现场数据
解读
面试官问“在iOS使用MetricKit收集现场数据”,表面看是考察iOS原生能力,实则是验证候选人能否把Unity运行时性能数据无缝对接到苹果官方现场监控体系,并在U3D项目里闭环落地。国内大厂上线iOS游戏必须过苹果审核+版号合规,任何崩溃、卡顿、发热都会被商店直接下架,MetricKit 是苹果官方唯一允许后台收集的“合法”现场性能数据源。答不出=暴露“只会写脚本,不懂国内iOS上线生死线”。
知识点
- MetricKit 生命周期:每日凌晨系统回调
MXMetricManager.didReceive(_:),仅给过去24h聚合数据,不能实时采样。 - 可采集的Unity相关维度:
- CPU/GPU 时间片(对应Unity.PlayerLoop占用)
- 挂起率(AppEnterBackground 时Unity没释放RenderTexture导致)
- 磁盘写入(Unity缓存/热更AB包写入)
- 电池电量下降率(Unity高帧渲染+IL2CPP峰值)
- 原生桥接:Unity→C#→OC 需要走
UnitySendMessage+NSNotificationCenter双通道,主线程同步回掉,防止Unity侧因子线程访问iOS UIKit崩溃。 - 合规存储:MetricKit 原始
MXMetricPayloadJSON 体积可达200k,国内版号要求本地加密缓存(iOS FileProtectionCompleteUntilFirstUserAuthentication),再上链企业微信/飞书告警。 - 版本差异:iOS 14+ 才支持
MXSignpostMetric,老机型占比国内仍有18%,需运行时if (@available(iOS 14, *))降级,否则审核打回。
答案
-
在Unity Assets/Plugins/iOS 新建
MetricKitBridge.mm- 引入
@import MetricKit; - 实现单例
MetricKitCollector,在+ (void)load注册[[MXMetricManager sharedManager] addSubscriber:self]; - 系统回调
didReceiveMetricPayloads:里把MXMetricPayload转JSON字符串,通过UnitySendMessage("MetricKitManager", "OnPayload", jsonUTF8)抛回C#。
- 引入
-
C#层封装
- 新建
MetricKitManager.cs,声明extern void _StartMetricKit(); - 收到JSON后使用
UnityEngine.JsonUtility反序列化为MetricKitPayload结构体,提取cpuMetrics.cumulativeCPUTime/gpuMetrics.cumulativeGPUTime,按场景名哈希归档到Application.persistentDataPath/mk_<date>.log。
- 新建
-
数据上报
- 次日启动时读取本地
.log,AES-128-CBC加密,key存于iOS Keychain; - 使用Unity
UnityWebRequest.Post上传到公司OSS,Header带x-apple-mk-version方便后台对齐苹果官方指标; - 若某指标超过苹果推荐阈值(如CPU>40ms/frame),触发企业微信机器人告警,并自动在Jira创建“iOS性能Blocker”工单。
- 次日启动时读取本地
-
热更兼容
- 若项目使用HybridCLR,需在
MetricKitBridge.mm加__attribute__((visibility("default"))),防止il2cpp裁剪符号; - 对于iOS 13老设备,兜底用
PLCrashReporter采集堆栈,与MetricKit数据关联,保证全版本覆盖。
- 若项目使用HybridCLR,需在
-
审核要点
- Info.plist 必须声明
NSMetricKitUsageDescription,中文描述“用于分析游戏性能,提升用户体验”,否则审核4.0条款直接拒绝; - 不允许在后台主动唤醒采集,只能被动等系统回调,否则会被苹果判为“异常后台活动”。
- Info.plist 必须声明
拓展思考
- 如何把MetricKit的“挂起率”与Unity的
OnApplicationPause关联,精准定位是脚本阻塞还是渲染线程未释放? - 当项目使用URP+Unity6,GPU时间片在iPhone 15 Pro上仍超过16ms,MetricKit只能给出总量,如何结合Xcode GPU Frame Capture在U3D里做自动化回归?
- 国内渠道包(如腾讯应用宝)需要双端对齐指标,是否考虑把MetricKit数据映射到Android的
Play Core Performance API,实现一套跨平台性能看板?