我使用 GameCenter 和实时服务器-客户端网络策略创建了一个纸牌游戏。在沙盒中进行测试时,游戏运行完美(建立连接、选择最佳主机、发送/接收数据),有时游戏甚至可以毫无问题地完成。然而,大多数时候,在两台设备上我都会收到一个 match:player:didChangeState: 回调,通知我对方用户已断开连接。它经常令人沮丧地发生,并且似乎与不活动或超时没有任何关系。我的想法是我可能正在处理 GameCenter 服务器上的正常网络延迟,因为在极少数情况下玩家似乎重新连接并再次发送数据。还有其他人使用 GKMatch 和 Real Time GameCenter 处理这些问题吗?我正在运行 iOS 6.1 并连接到同一个 wifi 网络的 iPhone 5 和 iPhone 4 上测试该应用程序。
2 回答
对于 MAX player=2,我遇到了同样的问题。对我来说 GKMatch 的代表
- (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state;
即使用户在游戏中处于活动状态,也将“状态”返回为“GKPlayerStateDisconnected”。对我有用的解决方案如下:在我的 NetworkManager 类中,我将当前匹配引用为 gkMatch。因此,每当我再次将“状态”设为“GKPlayerStateDisconnected”时,我都会检查它是否真的与远程播放器断开连接。为此,我使用了“gkMatch”数据,如下所示: ps:如果会话实际上没有断开,它包含字符串为“已连接”。
NSString *gkMatchString = [NSString stringWithFormat:@"%@",[NetworkManager sharedManager].gkMatch];
if ([gkMatchString rangeOfString:@"connected"].location == NSNotFound)
{
NSLog(@"Session is actually closed.");
}else{
NSLog(@"Session is NOT yet closed.");
}
它对我有用,所以如果它对任何人有帮助,请告诉我。
虽然我没有找到断开连接的确切解决方案,但我用以下方法解决了我的问题。此外,为了防止在断开连接期间发送的消息丢失:我实现了一个“响应”处理程序,用于检测消息是否被对手实际接收(因为当对手没有收到消息时,可靠数据发送模式不会出错由于连接问题)。
当游戏开始时,我确定一个用户是主机(选择BestHostPlayerWithCompletionHandler:^),当我检测到断开连接时,主机玩家重新邀请非服务器玩家回到游戏中。无论游戏是通过邀请还是“立即玩”开始的,这都有效。它解决了我的“ShouldReconnect”问题,该问题仅适用于 1v1 和邀请匹配。当非主机玩家接受邀请时,我以编程方式完成匹配以防止 MatchMakerViewController 出现在屏幕上。重新连接后,比赛将毫无问题地继续进行。
- (void)reinvitePlayer {
GKMatchRequest *request = [[GKMatchRequest alloc] init];
request.minPlayers = 2;
request.maxPlayers = 2;
request.playersToInvite = @[_opponent.playerID];
request.inviteMessage = @"Reconnect?";
request.inviteeResponseHandler = ^(NSString *playerID, GKInviteeResponse response)
{
DLog(@"Player response = %i.",response);
// [self updateUIForPlayer: playerID accepted: (response == GKInviteeResponseAccepted)];
};
[[GKMatchmaker sharedMatchmaker] addPlayersToMatch:_match matchRequest:request completionHandler:^(NSError *error) {
if (error != nil) {
DLog(@"Unable to add player to match.");
} else {
DLog(@"Successfully reconnected");
[[GKMatchmaker sharedMatchmaker] finishMatchmakingForMatch:_match];
}
}];
}