离线游戏中心iOS成就

Kir*_*kov 9 objective-c achievements ios game-center

在离线模式下(例如,打开飞行模式),尝试找出在Game Center中使用成就的最佳方式.

据我所知,iOS 5+中的Game Center负责离线提交的成就和分数.它就像一个代理缓存,并在用户上线时将它们提交到在线游戏中心.考虑到这一点,我在做什么:

用户身份验证成功时,我加载成就并将它们存储在字典中.

[GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *gcAchievments, NSError *error)
{
    if (error) { ..skipped ..}
    //This dictionary will store current achievments, so that we didn't submit them
    //once more and didn't show notification.
    achievments = [[NSMutableDictionary alloc] initWithCapacity:gcAchievments.count];

    //Storing achievments in dictionary
    for(GKAchievement *a in gcAchievments)
        [achievments setObject:a forKey:a.identifier];       
}];
Run Code Online (Sandbox Code Playgroud)

稍后当我提交新成就时,我会在字典中检查成就,如果成就已经完成,则不提交.如果我提交成就,我也会将其添加到achievments字典(内存中),以立即重新表明已经提交了此成就.

GKAchievement *cachedAchievment = [achievments objectForKey:identifier];
if (cachedAchievment && cachedAchievment.percentComplete >= 100)
{
    //Already unlocked this achievment.
    return;
}

GKAchievement *achievement = [[GKAchievement alloc] initWithIdentifier: identifier];
if (achievement)
{
    achievement.percentComplete = percent;
    [achievement reportAchievementWithCompletionHandler:^(NSError *error)
     {
         if (!error)
         {
             //Flagging achievment as completed locally to avoid achieving it second time and showing notification.
             [achievments setObject:achievement forKey:achievement.identifier];

             //Now shoing notification banner.
             GKAchievementDescription * desc = [achievmentsDescriptions objectForKey:achievement.identifier];
             [[GKAchievementHandler defaultHandler] notifyAchievement:desc];
         }
         else
         {
             NSLog(@"Error in reporting achievements: %@", error);
         }
     }];
}
Run Code Online (Sandbox Code Playgroud)

这种方法允许我在游戏代码中触发提交,但是我会提交两次成就或两次显示通知横幅.

当Game Center在线时,一切正常.但是,如果我离线,我有2个问题.

  1. 加载代码返回错误并且初始字典achievments没有填充已经完成的成就,这意味着每次用户启动游戏时他/她再次获得每个成就的通知横幅,即使它已被授予.然后在它被放入字典之后它不会显示,但我不希望每次游戏开始都显示一次成就.

  2. 我不确定当用户上线时,离线提交的成就是否会到达Game Center.我可以使用持久存储(如数据库)来解决问题#1,以便在游戏启动之间存储成就状态,但是当Game Center在线时我应该重新提交它们吗?如何检测Game Center是否实际在线,因为即使离线reportAchievementWithCompletionHandler完成也没有错误,所以我无法检测它是否未提交.这是我正在测试的方式,我打开飞机模式,解锁一些成就,然后关闭飞机模式,成就不到达游戏中心,尽管这可能是"沙盒"问题.

joh*_*vin 4

添加您提到的“成就已解锁”的持久存储,并为每个成就存储“已成功提交到游戏中心”标志。然后,在线时,检查启动时的结果loadAchievementsWithCompletionHandler并定期检查每个成就是否unlocked && !submitted确实已到达游戏中心,如果没有,请重新提交。