当matchData更改时,不能可靠地调用基于GameKit回合的侦听器 [英] GameKit Turn-based listener is not reliably called when matchData changes

查看:56
本文介绍了当matchData更改时,不能可靠地调用基于GameKit回合的侦听器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在纸牌游戏中使用的是Game Center回合制比赛.感觉很合适,因为人们有时想在轮流之间检查他们的电子邮件或写文本.一些用户说过,他们确实希望能够获得非常异步的播放体验.

I am using Game Center turn-based matches for my card game. It feels like a good fit because people want to check their email or write a text sometimes between turns. Some users have said that they do really want to be able to have a very asynchronous playing experience.

对于那些在回合之间保持游戏开放的人们,我想更新屏幕以反映其他玩家在回合中所做的事情.我已经在GKLocalPlayer上设置了一个响应player:receivedTurnEventForMatch:didBecomeActive的侦听器.该文档说,当比赛数据被另一位球员保存时,即使未成为该球员的回合(当前设备上的球员),也会调用此方法.似乎并非100%的时间都是正确的.实际上,似乎只有三分之一的调用率被其他玩家保存的匹配数据所吸引.轮到玩家看时,它似乎更可靠,但即使那样也不是100%可靠.

For the people that are keeping the game open between their turns, I want to update the screen to reflect things that the other players are doing on their turns. I have set up a listener on GKLocalPlayer that responds to player:receivedTurnEventForMatch:didBecomeActive. The documentation says that this will get called when match data is saved by another player even if it doesn't become the player's turn (the player on the current device). That doesn't appear to be true 100% of the time. In fact, it appears that it only gets called about 1 in 3 times that match data is saved by other players. It seems more reliable when it becomes the player's turn, but even that isn't 100% reliable.

我正在使用GKTurnBasedMatch上的saveCurrentTurnWithMatchData:completionHandler:来保存未结束当前玩家回合的比赛数据,而我正在调用GKTurnBasedMatch上的endTurnWithNextParticipants:turnTimeout:matchData:completionHandler:以在结束当前玩家的回合时保存数据.在某些情况下,我想使用更新的matchData调用saveCurrentTurn….在我的游戏中,您也可以让计算机在多人游戏中玩.因此,人类玩家可以玩纸牌,然后计算机可以在GKPlayer的回合结束之前玩纸牌.在某些情况下,单个玩家可能玩两次. (例如,某位玩家在某把戏中使用了最后一张纸牌.该名玩家使用了该把戏并领导了下一个把戏.)

I am using saveCurrentTurnWithMatchData:completionHandler: on GKTurnBasedMatch to save match data that doesn't end the current player's turn and I'm calling endTurnWithNextParticipants:turnTimeout:matchData:completionHandler: on GKTurnBasedMatch to save the data when it does end the current player's turn. There are a few scenarios where I want to call saveCurrentTurn… with updated matchData. In my game, you can have computers playing in your multiplayer game as well. So, a human player may play a card and then a computer may play a card before that GKPlayer's turn ends. There are also scenarios where an individual player may play twice. (eg. A player plays the last card on a trick. That player takes the trick and gets to lead the next trick.)

我已经建立了大量日志记录,并且可以看到清晰的场景,其中一个设备调用saveCurrentTurn…,并且调用completedHandler时没有错误,而另一设备没有通过调用player:receivedTurnEvent…的方式得到通知我还添加了日志记录,以验证每次调用saveCurrentTurn…时是否都使用新的matchData进行调用.我没有打多余的电话.

I have set up a ton of logging around this and I can see clear scenarios where one device calls saveCurrentTurn… and the completionHandler is called without an error and the other device doesn't get notified with a call to player:receivedTurnEvent… I have also added logging to verify that each time I'm calling saveCurrentTurn… that I'm calling it with new matchData. I'm not making redundant calls.

如果我转到未获取更新的matchData的设备,并强制其再次为比赛加载matchData,则它将获取更新的数据.因此,它肯定会被保存.

If I go to the device that didn't get the updated matchData and force it to load the matchData for the match again, it gets the updated data. So, it's definitely getting saved.

我已尝试限制对saveCurrentTurn…的调用,以使它们不会立即连续发生,并且无济于事.

I have tried throttling the calls to saveCurrentTurn… so that they don't happen in immediate succession and that didn't help.

我测试中的两个设备都运行iOS 8.4. iOS 8.3中似乎有一个现已解决的问题(请参阅此问题). 此Apple论坛帖子也在2年前报告了此问题,并且似乎错误报告已归档并标记为已修复.

Both devices in my testing are running iOS 8.4. There appears to have been an issue in iOS 8.3 that is fixed now (see this question). This Apple forum post also reports this issue 2 years ago and it appears that bug reports were filed and marked fixed.

还有其他人看到过吗?我很想知道我做错了什么.任何想法都非常欢迎.

Has anyone else seen this? I would love to know that I'm doing something wrong. Any ideas are very welcome.

推荐答案

我做了类似的事情.在我的游戏中,每个玩家都有多个棋子,当每个棋子移动时保存比赛,以便其他玩家(如果他们在游戏中)可以实时观察正在发生的事情.正如您所描述的,Game Center消息几乎是完全无用的.

I do something similar. In my game, each player has multiple pieces, saving the match when each piece moves so that other players--if they're in the game--can watch what's happening in real time. Like you describe, the Game Center messaging is almost completely useless.

正如您在8.3中所引用的,回合结束"消息已被完全破坏.从8.4版开始,它们发生的时间最多,但不是全部.如您所见,匹配已保存"通知也不稳定.以下是一些我用来提高成功率的技巧:

As you referenced, in 8.3, the "end of turn" messages were completely broken. As of 8.4, they happen most, but not all, of the time. As you're seeing, the "match has been saved" notifications are also erratic. Here are some tips I've used to increase the success rate:

  1. 降低保存速度.如果您保存得太快,则只有最后一个到达收件人.我设置了一个NSArray队列,每次我想要保存匹配项时,我都会将新的matchData添加到该队列中.我正在运行一个执行实际saveCurrentTurnWithMatchData的计时器循环,如果保存成功,则将该项目从堆栈中弹出,然后设置一个新的计时器,以便稍后再调用一次.我正在使用2秒的间隔,这似乎效果很好.

  1. Slow down the saves. If you save too fast, only the last one arrives at the recipient. I set up an NSArray queue, and each time I want to save the match, I add the new matchData to that queue. I have a timer loop running that does the actual saveCurrentTurnWithMatchData, pops the item off the stack if the save was successful, and then sets up a new timer to call itself again a little later. I'm using 2 second intervals which seems to be working well.

附加每个新数据,请勿覆盖.在每个数据上放置一个序列号.因此,如果您保存序号1、2、3和4,但是收件人仅收到#4的通知,则匹配对象中将存在1、2和3的记录.接收者需要跟踪其读取的最后一条记录,然后在接收到更新的matchData时从该点开始遍历任何新记录.

Append each new piece of data, don't overwrite. Put a sequence number on each piece of data. So, if you save seq numbers 1, 2, 3 and 4, but the recipient only receives a notice for #4, the records for 1, 2 and 3 are there in the match object. The recipient needs to track the last record it read, and then iterate through any new records from that point when it receives an updated matchData.

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

I also use the queue's NSArray writeToFile: function to maintain a list of the pending saves. If the user exits the game before the queue is flushed, I reload the queue NSArray from disk at the next startup

请注意,即使使用这种机制,发送给收件人的通知也是不稳定的.一般来说,它们以4+分批到达.然后什么也没有发生,直到再保存3或4次,所有这些又一起出现.保存1并将游戏放置10分钟可能永远不会在接收者的计算机上发出通知.但是,如果您连续保存4或6次,则所有这些都可能会突然出现.

Note that even with this mechanism, the notifications to the recipient are erratic. Generally speaking, they arrive in batches of 4+. Then nothing happens until 3 or 4 more saves happen, which again all show up together. Making 1 save and letting the game sit for 10 minutes will probably never generate a notice on the recipient's machine. But, if you save 4 or 6 times in a row, all of them tend to show up in a burst.

有时,通知只会停止几个小时.不确定这是沙盒漏洞还是一般游戏中心漏洞.没有任何类型的故障,消息只会停止一段时间.有时,第二天早晨,它们突然出现.有时不是.最后,我不再依赖通知了.我设置了另一个计时器循环来连续下载比赛.它检查是否轮到我了,它检查是否将新的更新添加到matchData中.然后调用player:receivedTurnEventForMatch:didBecomeActive.到目前为止,receivedTurnEventForMatch:知道,它是由于某个事件而启动的,它很愉快地开展业务.

Sometimes, the notifications just stop for a few hours. Not sure if this a sandbox flaw or a game-center-in-general flaw. There are no failures of any kind, the messages just stop working for a while. Sometimes, the next morning, they show up in a burst. Sometimes not. In the end, I've stopped relying on the notifications. I set up another timer loop to continuously download the match. It checks if it has become my turn or not, it checks if new updates have been added to the matchData. Then calls player:receivedTurnEventForMatch:didBecomeActive. As far a receivedTurnEventForMatch: knows, it was launched because of an event and it merrily goes on about its business.

似乎确实很容易保存比赛.如果您没有遇到任何错误,似乎可以肯定的是,其他玩家可以立即使用更新后的比赛……他们只需要知道如何使用它即可.但是,必须将消息传递框架视为完全不可靠且没有保证的框架.因此,计时器循环不断轮询匹配项.

It does seem that saving the match is pretty prompt. If you don't get an error, it seems pretty certain that the updated match is immediately available for other players to consume... they just need to know to consume it. The messaging framework, though, has to be viewed as completely unreliable and non-guaranteed. Hence, the timer loop to continuously poll the match.

可以说,一旦我实现了#2,#1其实就不重要了.收件人收到的任何通知都将触发读取数据中的所有新记录.但是,随着我努力克服Game Center的缺点,这种强化"在过去几个月中得到了发展.我只是还没办法删除#1.

arguably, once I implemented #2, #1 shouldn't really matter. Any notification received by the recipient will trigger reading all new records in the data. But, this "hardening" has evolved over the past few months as I wrestle with Game Center's shortcomings. I just haven't gotten around to removing #1.

这篇关于当matchData更改时,不能可靠地调用基于GameKit回合的侦听器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆