Game Center多人配对问题

问题描述 投票:0回答:3

我正在尝试使用 Game Center 创建实时多人游戏。对于匹配,我使用以下代码使用编程方法:

[[GKMatchmaker sharedMatchmaker] findMatchForRequest:request withCompletionHandler:^(GKMatch *match, NSError *error) {
        if (error)
        {
            // Process the error.
            NSLog(@" error => %@ ", [error userInfo] );

        }
        else if (match != nil)
        {
            NSLog(@"Match Found _-----------");
            currentMatch = match;
            match.delegate = self;

            NSLog(@"Expected player count:%ld",match.expectedPlayerCount);

            if ( match.expectedPlayerCount == 0)
            {
                NSLog(@"Ready to start match!");

            }
        }
    }];

目前,当找到匹配项时,代码会生成以下错误:

ABC-mobile[342:26698] [log]  [ERROR] ReXmitCollectionRequest:640 /BuildRoot/Library/Caches/com.apple.xbs/Sources/AVConference/AVConference-1020.31/ICE.subproj/Sources/ICEMessage.c:640:     ReXmit [SNATMAP_REQUEST] (1:0) from [192.168.0.104:16402] to [17.133.234.32:16384] failed (801A0002)

ABC-mobile[342:26698] [log]  [ERROR] -[GKConnectionInternal internal_setRemoteConnectionData:fromParticipantID:pendingConnectionPIDList:]:1041 GCKSessionPrepareConnection FAILED(80150016)

我正在使用 Cocos2D-X 游戏引擎,并且我从 C++ 函数调用此方法。

我将不胜感激有关此主题的任何建议和想法。谢谢你。

objective-c cocos2d-x game-center
3个回答
0
投票

解决方案:

使用纯 Objective-C 代码(文件扩展名应为 .m 而不是 .mm)。在 Objective-C++(扩展名为 .mm 的文件)中编写一个包装类来调用这些 Game Center 方法。


0
投票

我最近遇到了这个问题,网上关于它的信息很少。

2023-10-31 17:44:22.256821+0900 Real-Time Game Sample[663:76416] [ViceroyTrace]  [ERROR] ReXmitCollectionRequest:629 /Library/Caches/com.apple.xbs/Sources/AVConference/ICE.subproj/Sources/ICEMessage.c:629:   ReXmit [SNATMAP_REQUEST] (1:0) from [183.102.108.243:16402] to [17.188.182.97:3480] failed (801A0002)
2023-10-31 17:44:22.258946+0900 Real-Time Game Sample[663:76416] [ViceroyTrace]  [ERROR] ReXmitCollectionRequest:629 /Library/Caches/com.apple.xbs/Sources/AVConference/ICE.subproj/Sources/ICEMessage.c:629:   ReXmit [SNATMAP_REQUEST] (1:0) from [183.102.108.243:16402] to [17.188.182.97:3480] failed (801A0002)
... HUNDREDS MORE...
2023-10-31 17:44:26.736101+0900 Real-Time Game Sample[663:76416] [ViceroyTrace]  [ERROR] ReXmitCollectionRequest:629 /Library/Caches/com.apple.xbs/Sources/AVConference/ICE.subproj/Sources/ICEMessage.c:629:   ReXmit [SNATMAP_REQUEST] (1:0) from [183.102.108.243:16402] to [17.188.182.97:3480] failed (801A0002)
2023-10-31 17:44:26.737198+0900 Real-Time Game Sample[663:76416] [ViceroyTrace]  [ERROR] ReXmitCollectionRequest:629 /Library/Caches/com.apple.xbs/Sources/AVConference/ICE.subproj/Sources/ICEMessage.c:629:   ReXmit [SNATMAP_REQUEST] (1:0) from [183.102.108.243:16402] to [17.188.182.97:3480] failed (801A0002)
2023-10-31 17:44:26.738326+0900 Real-Time Game Sample[663:76416] [ViceroyTrace]  [ERROR] -[GKConnectionInternal internal_setRemoteConnectionData:fromParticipantID:pendingConnectionPIDList:]:1047 GCKSessionPrepareConnection FAILED(80150016)

Viceroy 显然是

GameKit
用于实时连接的点对点连接框架。这是一个内部错误,不提供任何失败原因的信息。

当满足

GKMatch
请求后生成的
findMatch
对象没有
delegate
时,就会发生这种情况。它尝试将信息推送给委托,但失败,导致会话无法连接。

例如,如果您有

    public func findPlayer() async {
        let request = GKMatchRequest()
        request.minPlayers = 2
        request.maxPlayers = 2
        let match: GKMatch
        
        do {
            match = try await GKMatchmaker.shared().findMatch(for: request)
        } catch {
            print("Error: \(error.localizedDescription).")
            return
        }
        
        start(match: match)

        GKMatchmaker.shared().finishMatchmaking(for: match)
    }

然后

start(match:)
函数看起来像这样

    public func start(match: GKMatch) {
        guard match.expectedPlayerCount == 0
        else {
            return
        }
        
        currentMatch = match
        currentMatch?.delegate = self
    }

请注意,委托不是根据

expectedPlayerCount
是否为 0 设置的。这导致了失败,在找到匹配项后立即设置委托可以解决问题。

所以最终的工作解决方案如下:

    public func findPlayer() async {
        let request = GKMatchRequest()
        request.minPlayers = 2
        request.maxPlayers = 2
        let match: GKMatch
        
        do {
            match = try await GKMatchmaker.shared().findMatch(for: request)
        } catch {
            print("Error: \(error.localizedDescription).")
            return
        }
        
        currentMatch = match
        currentMatch?.delegate = self
        
        start(match: match)

        GKMatchmaker.shared().finishMatchmaking(for: match)
    }

    public func start(match: GKMatch) {
        guard match.expectedPlayerCount == 0
        else {
            return
        }
        
        // Start Game Logic
    }

    // MARK: - GKMatch Delegate
    public func match(
        _ match: GKMatch,
        player: GKPlayer,
        didChange state: GKPlayerConnectionState
    ) {
        switch state {
        case .connected:
            print("\(player.displayName) Connected")
        case .disconnected:
            print("\(player.displayName) Disconnected")
        default:
            print("\(player.displayName) Connection Unknown")
        }
        
        start(match: match)
    }

-1
投票

我绝不会建议在您自己的云基础设施上部署代码进行匹配。我使用 AWS lambda + dynamodb 组合做到了这一点。 Dynamo db 促进了表键上的原子操作。这些关键点可能是你匹配玩家的技能点。 Firebase云功能+RealtimeDB(也可以尝试CloudStore。这是Firebase的新产品)是开发匹配框架的另一种选择。它不提供密钥的原子性,但还有另一个 PushKey 的概念。这也有效。

这两家都是主要的云供应商,因此您不必担心延迟或停机。我在美国的 Firebase RealtimeDB 上建立了我的中心,在印度,我能够在 500 毫秒内将事件传输给印度的另一位玩家。

这两者都有一定的免费连接/请求限制(我猜 Firebase 的免费连接数量比 AWS 更多。您可能需要检查一下)。因此,在您的游戏真正开始赚钱之前,您很长一段时间都不会产生任何费用。在我的 AWS Lambda + DynamoDB 组合上,我每天可以进行 11k 次匹配,而无需支付一分钱。

最重要的是,这两个国家都提供区域中心。因此,当您扩大规模时,您可以创建多区域中心。

但是这两个供应商可能都不支持 C++ 或 Objective-C++。我在 Javascript 和 JAVA 上开发了我的模型。也许也支持其他一些语言。您可能想检查一下。

© www.soinside.com 2019 - 2024. All rights reserved.