游戏中心多人游戏使用GKMatch,但似乎无法连接。

4

你好,我是一个iOS游戏中心的新手。我正在尝试使用比赛功能为我的游戏添加多人游戏,并遵循文档。

到目前为止,我已经达到了两个客户端成功匹配的地步,也就是matchmakerViewController:didFindMatch回调被调用并且GKMatch对象被传递。

然而,在那之后,我似乎永远卡在那里,因为根据文档,我必须等待所有玩家(在我的情况下是2个)实际连接才能开始游戏。但是,似乎match:player:didChangeState回调从未被调用以指示成功连接。嗯,我确定我的客户端都在同一个WiFi网络中(或者这是必须的吗?)有没有人能为我解答一下这个问题?我需要做额外的事情来使客户端连接吗?非常感谢您的帮助!


1
最近对这个问题进行了一些更新,我最终使用Wireshark捕获了所有的流量,并发现Game Center需要使用STUN来克服路由器/NAT/防火墙的限制。通过查看RFC,它说:“当用于获取与位于同一NAT后面的对等方通信的地址时,STUN无法工作。”好吧,我想这可能是我的问题根源,我的两个客户端都在WiFi路由器的私有网络(192.168.2.x)中。但我不确定在测试时克服这个问题的最佳方法是什么...有什么想法吗? - Albert Wang
3
我和你一样也有同样的问题,但我不认为你上面提到的STUN问题是原因,因为我对连接了两个不同NAT网络的设备进行测试。 - thomdask
6个回答

3

我遇到了这个问题,解决方法(对我来说)有点尴尬。我从苹果文档中复制粘贴了一堆代码...他们漏掉了一个显而易见的步骤。他们实际上从未设置匹配项的代理!

现在我的代码是:

- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *)match {
[self dismissModalViewControllerAnimated:YES];
self.myMatch = match; // Use a retaining property to retain the match.
self.myMatch.delegate = self;  // THIS LINE WAS MISSING IN THE APPLE DOCS.  DOH.
// Start the game using the match.
NSLog(@"Match started! Expected Player Count:%d  %@",match.expectedPlayerCount, match.playerIDs);}

一旦我真正设置了匹配委托,函数就会被调用。 哦。


2

当您获取GKMatch对象时,请务必检查expectedPlayerCount属性。可能其他玩家已经连接,因此您将不会在委托上收到match:player:didChangeState的回调。


相同的代码在相同的NAT中可以工作,但在不同的NAT中却不能。所以这不是问题所在。 - thomdask
你检查了这个属性吗?这完全是与时间有关的,因此在不同的网络上会有不同的行为。 - nrp

1
在你的回调函数matchmakerViewController:didFindMatch中,添加以下代码,然后你就会看到GC调用了回调函数"match:player:didChangeState"。
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
    request.minPlayers = 2;
    request.maxPlayers = 2;
    [[GKMatchmaker sharedMatchmaker] addPlayersToMatch:match matchRequest:request completionHandler:^(NSError* error) {
        if(error)
            NSLog(@"Error adding player: %@", [error localizedDescription]);
    }];

1

我和一个朋友遇到了同样的问题。解决方案很奇怪,但之后它确实有效。在所有设备上,您必须在“设置/通知”选项中启用游戏中心的通知(声音/警报/标记)。之后,我们就可以建立连接并接收到匹配对象。


我不确定这是否有效,因为我正在使用iOS模拟器进行开发测试。其中一个运行在我的本机机器上,另一个运行在OS X服务器上的VMware中。通知不包含在iOS模拟器中。 - thomdask

1

一直都是可以工作的。唯一的区别是...当你使用邀请时,事件“didChangeState”不会被调用。你已经连接上了,可以开始接收数据。我从未尝试发送/接收数据...因为我在等待事件的发生,但有一次我不小心发送了一些东西,结果它却奏效了。 :)

- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *) match {    
    //Dismiss window
    [self dismissModalViewControllerAnimated:YES];

    //Retain match
    self.myMatch = match; 

    //Delegate
    myMatch.delegate = self;


    //Flag
    matchStarted = TRUE;

   //Other stuff
}

- (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state  {
    //This code gets called only on auto-match
}

上述代码按预期工作。


0

请确保您已将您的类设置为GKSession的代理。该类需要实现GKSessionDelegate协议...否则,它将永远无法接收到此回调。这是协议参考。希望这可以帮助您!


谢谢Sam,但我实际上是在使用match而不是peer-to-peer来实现Multiplay。所以我已经正确地实现和设置了GKMatchDelegate协议和GKMatchmakerViewControllerDelegate,但似乎无法接收到match:player:didChangeState的回调。 - Albert Wang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接