9

オフライン モード (機内モードがオンになっているなど) の場合に Game Center で実績を操作するための最良の方法を見つけようとしています。

私の知る限り、iOS 5 以降の Game Center は、オフラインで提出された実績とスコアを処理します。これはプロキシ キャッシュのように機能し、次にユーザーがオンラインになったときにそれらをオンラインの 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];       
}];

後で新しいアチーブメントを提出するとき、辞書でアチーブメントをチェックし、アチーブメントがすでに完了している場合は提出しません。アチーブメントを送信すると、それを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);
         }
     }];
}

このアプローチにより、ゲーム コードで送信をトリガーすることができ、アチーブメントを 2 回送信したり、通知バナーを 2 回表示したりすることを心配する必要はありません。

Game Center がオンラインの場合、Everyting は正常に動作します。しかし、オフラインの場合、2 つの問題があります。

  1. コードをロードするとエラーが返され、 の初期ディクショナリにachievmentsはすでに完了したアチーブメントが入力されていません。これは、ユーザーがゲームを起動するたびに、アチーブメントがすでに授与されている場合でも、各アチーブメントの通知バナーを再度受け取ることを意味します。その後、辞書に配置された後は表示されませんが、ゲームの開始ごとに実績を一度も表示したくありません。

  2. ユーザーがオンラインになったときに、オフラインで送信された実績が Game Center に届くかどうかはわかりません。永続的なストレージ (データベースなど) を使用してゲームの起動間の達成状況を保存することで問題 #1 を解決できますが、Game Center がオンラインのときにそれらを再送信する必要がありますreportAchievementWithCompletionHandler。そのため、送信されていないかどうかを検出できません。これが私がテストしている方法です。機内モードをオンにし、いくつかの実績のロックを解除してから機内モードをオフにしました。これは「サンドボックス」の問題かもしれませんが、実績はゲームセンターに届きません.

4

1 に答える 1

4

言及した「成果のロックが解除されました」の永続ストレージを追加し、各成果の「Game Center に正常に送信されました」フラグも保存します。次に、オンラインのときに、loadAchievementsWithCompletionHandler起動時および定期的に結果を確認して、各実績unlocked && !submittedが実際に Game Center に到達したかどうかを確認し、到達していない場合は再送信します。

于 2013-02-20T08:54:58.077 に答える