iOS 足迹 App 的成就系统,我推倒重做了一次——踩了3个坑之后

上线三周,成就页的打开率掉到了 2%。我盯着这个数字看了好一会儿,意识到设计完全错了。

「雁过留痕」是我做的一个足迹记录 App,核心思路是把你走过的路变成可量化的探索面积(km²),用 25m 精度网格覆盖地图,慢慢把省份和城市染色。这个核心玩法我觉得还不错,但成就系统上线之后直接拖了后腿。

第一版成就系统到底错在哪

最早的版本只有几个维度:总距离、总录制天数、省份解锁数量。听起来挺完整,上线之后发现问题很具体------用户解锁了头三个徽章,然后成就页就再也不打开了。

原因其实事后想想很显然:目标太稀疏,中间段完全是空白期。你解锁了「初探者」,下一个目标要再走 500km 才能到「漫游者」,这中间几个月看不到任何进展反馈,等于告诉用户「别来了」。

游戏设计里有个基本原则:玩家需要随时都能看到「我离下一个里程碑还有多远」。我第一版完全忽略了这件事。

推倒之后怎么重建

重做的核心思路是把成就拆成多个 Track,每个 Track 内部是连续的多级徽章,保证任意时刻都有「快到了」的感觉。

swift 复制代码
enum BadgeTrack: String, CaseIterable, Identifiable {
    case all
    case exploration   // 面积、城市、省份
    case consistency   // 连续打卡、累计月数
    case china         // 省级/大区解锁
    case world         // 全球探索
    case pro           // Pro 会员专属

    func matches(_ definition: BadgeDefinition) -> Bool {
        self == .all || definition.badgeTrack == self
    }
}

这个分组做出来之后,成就页的平均停留时长从 8 秒涨到了 19 秒。说实话这个数字比我预期高,主要原因我猜是「中国赛道」------省份解锁这个玩法对国内用户有天然吸引力,很多人打开成就页就是去看自己还差哪几个省。

数据聚合这块踩的坑

成就判断需要的数据维度很多:总距离、连续天数、省份数量、面积......最开始每个徽章自己去查数据库,成就页一打开要跑几十次查询,加载卡顿肉眼可见。

后来抽了一个 BadgeMetrics 结构统一做一次聚合,所有徽章判断共用同一份数据:

swift 复制代码
struct BadgeMetrics {
    let totalDistanceKilometers: Double
    let recordedDays: Int
    let currentStreakDays: Int
    let longestStreakDays: Int
    let chinaProvinceCount: Int
    let chinaAreaKm2: Double
    let cityUnlockCount: Int
    let globalAreaKm2: Double

    static func build(
        stats: TraceStats,
        segments: [TraceSegment],
        geo: GeographicProfile,
        proMembershipActive: Bool,
        proMembershipActivatedAt: Date?
    ) -> BadgeMetrics { ... }
}

顺带提一个细节:segments 在 build 里有一步过滤,只保留 pointCount >= 8 的记录。这个阈值对应大约 10-15 秒的有效移动,过滤掉了打开 App 又马上锁屏的噪声。这个数值调了好几次,太小的话徽章进度会被一堆无效数据撑高,用户觉得「奇怪,我没走多少怎么进度涨这么快」,反而破坏信任感。

中国坐标系的坑,顺便说一下

省份解锁要判断「这个 GPS 点是否在某个省内」,但 GPS 原始数据是 WGS-84,国内地图用 GCJ-02,直接拿坐标去匹配行政区边界,边境附近会出现「明明走在省内却没解锁」的情况。

我在 GeographicProfile 里做了坐标系转换,省级和地市级边界数据全部内置,不走网络请求。好处是离线也能正常触发成就,坏处是包体增加了大概 3MB------这个取舍我觉得值,足迹类 App 很多场景就是在没网络的山里。

现在纠结的一个设计问题

下一步想加「状态徽章」:比如「连续 30 天记录」解锁之后不是永久持有,断了会变灰,需要重新激活。

但我现在真的没想清楚该不该做。

没压力就没粘性,这个逻辑说得通,健身 App 基本都用这套。但足迹记录和健身不一样------用户可能就是出去旅行才开,平时根本不用,强迫他们「每天打卡」会让 App 变成一个焦虑来源。我不想做那种让人觉得「没开就有罪恶感」的产品。

但如果完全没有时间压力,成就全部永久持有,用户解锁完一批之后可能又回到当初那个 2% 的困境。

这个矛盾我现在还没有好答案。如果你做过类似的游戏化设计,或者作为用户对「会过期的成就」有什么感受,真想听听。

相关推荐
SameX2 小时前
我做了一个把专注计时变成「声音护照」的 iOS App,聊聊数据可视化和成长系统的设计思路
ios
SameX2 小时前
我用 SpriteKit 给存钱罐装了个物理引擎
ios
开心就好20252 小时前
Charles配置HTTP和HTTPS抓包完整指南
后端·ios
JarvanMo2 小时前
7 个开源 iOS 应用,让你成为更好的开发者
前端·ios
白玉cfc3 小时前
OC底层原理:alloc&init&new
c++·macos·ios·objective-c·xcode
ZZH_AI项目交付3 小时前
一个 iOS 埋点 SDK 从 0 到 1,再到真实项目接入打磨
ios·app·ai编程
2501_915918413 小时前
使用快蝎IDE进行iOS开发:从项目创建到真机调试全流程
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
iFlyCai3 小时前
iOS开发进阶:深入理解 Getter 与 Setter 的用法(超详细)
ios·objective-c·xcode
2501_9160088916 小时前
深入解析iOS应用启动性能优化策略与实践
android·ios·性能优化·小程序·uni-app·cocoa·iphone