当matchData更改

时间:2015-08-13 03:31:44

标签: ios game-center gamekit gkturnbasedmatch

我正在为我的纸牌游戏使用Game Center回合制比赛。这感觉非常合适,因为人们想要检查他们的电子邮件或有时在转弯之间写文本。一些用户表示他们确实希望能够拥有非常异步的游戏体验。

对于那些在轮到他们之间保持游戏开放的人,我想更新屏幕以反映其他玩家在轮流中正在做的事情。我在GKLocalPlayer上设置了一个响应player:receivedTurnEventForMatch:didBecomeActive的侦听器。文档说,当匹配数据被另一个玩家保存时,即使它没有成为玩家的回合(当前设备上的玩家),也会被调用。在100%的情况下,这似乎并不真实。事实上,它似乎只被召唤约3次,其他玩家保存匹配数据。当它变成玩家时,它似乎更可靠,但即使这样也不是100%可靠。

我在saveCurrentTurnWithMatchData:completionHandler:上使用GKTurnBasedMatch来保存未结束当前玩家的匹配数据,并且我在endTurnWithNextParticipants:turnTimeout:matchData:completionHandler:上呼叫GKTurnBasedMatch {1}}在数据结束当前播放器时保存数据。在某些情况下,我想使用更新的matchData调用saveCurrentTurn…。在我的游戏中,您也可以在多人游戏中玩电脑。因此,人类玩家可以玩牌,然后计算机可以在GKPlayer转牌结束之前玩牌。还有个别玩家可以玩两次的情况。 (例如,一名玩家在技巧上玩最后一张牌。该玩家接受该技巧并领先下一招。)

我已经设置了大量的日志记录,我可以看到一个设备调用saveCurrentTurn…并且没有错误地调用completionHandler并且其他设备没有通过呼叫通知的明确情况到player:receivedTurnEvent…我还添加了日志记录,以验证每次调用saveCurrentTurn…我是否使用新的matchData调用它。我没有拨打多个电话。

如果我转到没有获得更新的matchData并强制它再次为匹配加载matchData的设备,它将获取更新的数据。所以,它肯定会得救。

我已经尝试限制拨打saveCurrentTurn…的电话,以便它们不会立即发生并且没有帮助。

我测试中的两台设备都运行iOS 8.4。 iOS 8.3中似乎存在一个现在已修复的问题(see this question)。 This Apple forum post也在2年前报告此问题,并且看起来错误报告已归档并标记为已修复。

有没有人见过这个?我很想知道我做错了什么。任何想法都非常受欢迎。

1 个答案:

答案 0 :(得分:4)

我做了类似的事情。在我的游戏中,每个玩家都有多个棋子,在每个棋子移动时保存匹配,以便其他玩家 - 如果他们在游戏中 - 可以实时观察发生的事情。就像你描述的那样,Game Center的消息几乎完全无用。

如您所述,在8.3中,"转弯结束"消息完全被打破了。从8.4开始,它们在最多时发生,但并非全部发生。正如您所看到的,"匹配已被保存"通知也不稳定。以下是我用来提高成功率的一些提示:

  1. 减慢保存速度。如果保存太快,只有最后一个到达收件人。我设置了一个NSArray队列,每次我想保存匹配时,我都会将新的matchData添加到该队列中。我有一个运行的定时器循环,它执行实际的saveCurrentTurnWithMatchData,如果保存成功则将项目从堆栈中弹出,然后设置一个新的定时器,稍后再调用它自己。我使用了2秒的间隔,这似乎运作良好。

  2. 附加每个新数据,不要覆盖。在每个数据上放一个序列号。因此,如果您保存序号1,2,3和4,但收件人只收到#4的通知,则匹配对象中有1,2和3的记录。收件人需要跟踪它读取的最后一条记录,然后在收到更新的matchData时从该点迭代任何新记录。

  3. 我还使用队列的NSArray writeToFile:函数来维护待处理保存的列表。如果用户在刷新队列之前退出游戏,我会在下次启动时从磁盘重新加载队列NSArray

  4. 请注意,即使使用此机制,对收件人的通知也不稳定。一般来说,他们分批到达4+。然后没有任何事情发生,直到3或4次更多的保存发生,这一切再次出现在一起。进行1次保存并让游戏停留10分钟可能永远不会在收件人的机器上生成通知。但是,如果你连续保存4到6次,所有这些都会突然出现。

  5. 有时,通知会停止几个小时。不确定这是一个沙箱缺陷还是游戏中心一般的缺陷。没有任何类型的失败,消息只是停止工作一段时间。有时,第二天早上,他们突然出现。有时不是。最后,我已经停止依赖通知了。我设置了另一个定时器循环来连续下载匹配。它会检查它是否已轮到我,它会检查是否已将新更新添加到matchData。然后拨打player:receivedTurnEventForMatch:didBecomeActive。到目前为止receivedTurnEventForMatch:知道,它是因为一个事件而推出的,它很快就开始了它的业务。

  6. 似乎保存匹配非常及时。如果你没有收到错误,似乎很可能确定更新的匹配可以立即供其他玩家使用......他们只需要知道消费它。但是,消息传递框架必须被视​​为完全不可靠且无保证。因此,计时器循环连续轮询匹配。

  7. 编辑:可以说,一旦我实施#2,#1真的不重要。收件人收到的任何通知都将触发读取数据中的所有新记录。但是,这"强化"在过去的几个月里,我一直在与Game Center的缺点搏斗。我还没有去除#1。