2

如何检测 GameKit 自动匹配是否失败?

等待 2 分钟后,即使没有找到自动匹配的玩家,也会调用GKMatchmakerViewControllerDelegate matchmakerViewController:didFindMatch:。游戏中心的喇叭声甚至可以播放。我确信实际上没有找到任何玩家,因为这发生在 Game Center Sandbox 中,没有其他人可以访问我的应用程序。

当我尝试加载玩家*时,我收到一个错误,但必须有更好的方法来检查自动匹配失败,对吧?自动匹配失败时,有没有办法防止喇叭声凯旋?


*自动匹配失败时加载玩家显示错误:

[GKPlayer loadPlayersForIdentifiers:self.match.playerIDs withCompletionHandler:^(NSArray *players, NSError *error)
     {
         LOG_DEBUG(@"loadPlayersForIdentifiers completion handler called");
         if (error != nil)
         {
             LOG_ERROR(@"Error loading player information: %@", error);                 
         }
     }];

这显示以下错误:

加载播放器信息时出错:Error Domain=GKErrorDomain Code=17 “请求的操作无法完成,因为一个或多个参数无效。” UserInfo=0xb183a70 {NSLocalizedDescription=请求的操作无法完成,因为一个或多个参数无效。}


这是我用来调出 GameKit 比赛用户界面的代码:

GKMatchRequest *request = [[GKMatchRequest alloc] init];
request.minPlayers = 2;
request.maxPlayers = 2;
request.defaultNumberOfPlayers = 2;

GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc] initWithMatchRequest:request];
mmvc.matchmakerDelegate = self;

[self presentViewController:mmvc animated:YES completion:nil];

对于完整的上下文,我的整个应用程序是开源的,主视图控制器在这里:https ://github.com/jdimatteo/TeamRun/blob/master/TeamRun/TeamRun/TeamRunViewController.m

任何帮助是极大的赞赏!

4

2 回答 2

0

即使没有找到玩家,自动匹配也会成功。第二个(等等)参与者将是具有 nil ID 的非 nil 对象,并代表未来玩家匹配的占位符。如果无需将所有玩家都添加到游戏中就可以进行第一轮,这可以让游戏立即开始。

我想 loadPlayersWithIdentifiers 的错误是因为其中一些标识符是零。

您可以检查participant.playerID == nil并将其视为比赛尚未准备好,或者以任何对您的游戏有意义的方式处理它。

于 2013-08-21T01:55:08.140 回答
0

webjprgm 的答案仅与GKTurnBaseMatchesAFAIK 有关。从您的代码的外观来看,您正在实现实时匹配。

在实时匹配中,自动匹配只能保证成功。

我的意思是,在实践中,我发现它有时根本不会成功。但其他时候它返回一个空匹配。“空”是指它根本没有任何玩家甚至没有 wbjprgm 提到的“具有 nil ID 的非 nil 对象”,甚至没有

棘手的一点是,如果您返回一个空匹配项,有时该匹配项实际上很快就会被填充。但只是有时。其他时候,您可以永远等待并且不会被填满。

因此,为了监控这种情况,我必须做的事情很复杂,但它确实有效:

  • 在您的请求处理程序中,将任何返回的内容存储GKMatch为实例变量。我确定你已经这样做了。
  • 发送您的请求后,创建一个DispatchSourceTimer在 15 秒左右后运行任务*。DispatchSourceTimer在 Swift 中可用,同样的事情在 Objective-C 中是可行的但更复杂。
  • 该计时器必须在后台线程中运行。这个非常重要。这在高优先级队列中不起作用。
  • 在该任务中,检查两件事。
    • 检查该GKMatch实例变量是否为nil.
    • 如果不是nil,请检查其.players.count编号是否为0
  • 如果第一个条件为真,则取消匹配请求,并在取消的完成处理程序中,启动一个新请求和一个新计时器。
  • 如果第二个条件为真,做同样的事情,除了这次将计时器设置为在 20 秒内关闭(因为有时现有匹配需要更长的时间才能被填满,但你仍然不想闲逛永远)。

最终结果是您有一个请求自动匹配的循环循环,检查它是否成功,如果没有,则取消并重新启动请求。

我花了很长时间才使这个解决方案发挥作用,但当我这样做时,我对结果非常满意。是的,这是一个复杂的过程,如果有人想尝试,我祝他们好运,在 Game Kit 和 Grand Central Dispatch 的众多陷阱中顺利度过。

但值得一提的是,在我迄今为止的测试中,这从未失败过匹配两个请求自动匹配游戏的玩家。在我这样做之前,经常会出现两个请求游戏的玩家永远无法连接的情况。对我来说,它真的很好用。

*注意:我发现将计时器设置为少于 15 秒会使该过程极不可能成功。不完全确定为什么,但就是这样。

于 2017-03-03T15:36:11.913 回答