无法使用 GKMatchmaker.shared().findMatch 连接 GameKit 中的玩家
Can't connect players in GameKit using GKMatchmaker.shared().findMatch
我正在尝试在一个非常简单的游戏中使用 GameKit 将两个玩家相互联系起来。我想使用 GKMatchmaker.shared().findMatch
因为我不想显示任何与 GameCenter 相关的视图控制器。 (为简单起见)
问题:
即使 GameKit 在找到两名玩家后创建了一场比赛,也会发生一个错误,阻止任何一名玩家向其他玩家发送任何消息。
现状:
基本代码如下(基于此处描述的文档:https://developer.apple.com/documentation/gamekit/finding_multiple_players_for_a_game)
print("Requesting multiplayer match")
let request = GKMatchRequest()
request.minPlayers = 2
request.maxPlayers = 2
request.recipientResponseHandler = {(player: GKPlayer, respnse: GKInviteRecipientResponse) -> Void in
print("new player about to join")
print(player.alias)
print(respnse)
}
GKMatchmaker.shared().findMatch(for: request, withCompletionHandler: {
(match: GKMatch?, error: Error?) -> Void in
if error != nil {
// Handle the error that occurred finding a match.
print("error during matchmaking")
print(error as Any)
} else if match != nil {
guard let match = match else { return }
print("connected to \(match.players.count) players")
// load the multiplayer data handler
let handler = MultiMatchHandler()
match.delegate = handler
// load the multiplayer service
let service = MultiMatchService(match: match)
service.sendMessageToAll(text: "Hello from the other side")
// finish the match making
GKMatchmaker.shared().finishMatchmaking(for: match)
// Start the game with the players in the match.
self.view?.presentScene(GameScene.newScene(multiplayer: service))
}
})
那个的输出是
Requesting multiplayer match
2022-01-05 01:19:16.554959+0100 Grapefruit[38300:10026027] [Match] cannot set connecting state for players: (
"<GKPlayer: 0x282add280>(alias:... gamePlayerID:... teamPlayerID:... name:... status:(null) friendBiDirectional:0 friendPlayedWith:1 friendPlayedNearby:0 acceptedGameInviteFromThisFriend:0 initiatedGameInviteToThisFriend:0 automatchedTogether:1)"
), as there is no inviteDelegate set yet. The state might directly change to Ready when we set the inviteDelegate later and call sendQueuedStatesAndPackets.
2022-01-05 01:19:16.557002+0100 Grapefruit[38300:10026027] [Match] syncPlayers failed to loadPlayersForLegacyIdentifiers: (
"..."
)
connected to 0 players
sending text Hello from the other side failed
调查结果:
minPlayers
设置为 2。调用完成处理程序意味着至少找到了一名玩家。但是match.players.count
返回的玩家数是0
- 匹配器显示一个错误,指出
cannot set connecting state for players ... as there is no inviteDelegate set yet
。我找不到有关此邀请代表的任何信息。
实际问题:
什么是邀请代表?我真的需要实施这样的(如果是,那么如何实施?)? (我不这么认为,因为文档说明比赛仅在接受邀请后才开始)。
我该如何解决这个问题?
这是一个适合您的工作示例。在两台机器上打开,确保都经过身份验证,在两台机器上按“findMatch()”(并等待确认),然后 ping baby ping
我相信“尚未设置邀请代表”错误并不意味着必要的匹配失败,可以安全地忽略,如前所述here
您需要实现更多 GKMatchDelegate 协议,但这是用于演示目的的框架
import SwiftUI
import GameKit
import SpriteKit
class MyGameScene: SKScene, GKMatchDelegate {
override func didMove(to view: SKView) {
self.backgroundColor = .yellow
}
//GKMatchDelegate protocol
func match(_ match: GKMatch, didReceive data: Data, forRecipient recipient: GKPlayer, fromRemotePlayer player: GKPlayer) {
print("\(Self.self) \(#function) -- ping received")
}
}
struct Matchmaker: View {
@State var isAuthenticated:Bool = false
@State var scene = MyGameScene()
@State var match:GKMatch? = nil
var body: some View {
ZStack {
Color.clear
SpriteView(scene: scene)
VStack(alignment: .leading, spacing: 20) {
Text("1) authenticate() \(Image(systemName: isAuthenticated ? "checkmark.icloud" : "xmark.icloud"))")
Button { findMatch() } label: {
Text("2) findMatch() \(Image(systemName: (match != nil) ? "person.fill.checkmark" : "person.fill.xmark"))")
}
Button { ping() } label: {
Text("3) ping()")
}
}
}
.onAppear() {
authenticate()
}
}
func authenticate() {
GKLocalPlayer.local.authenticateHandler = { viewController, error in
if let error = error { print(error) }
isAuthenticated = (error == nil)
}
}
func findMatch() {
guard isAuthenticated else { return }
let request = GKMatchRequest()
request.minPlayers = 2
request.maxPlayers = 2
request.playerAttributes = 0xFFFFFFFF //mask for "i'll match with anyone"
GKMatchmaker.shared().findMatch (for: request) { match, error in
if let error = error { print(error) }
self.match = match
self.match?.delegate = scene
}
}
func ping() {
let players = match?.players ?? [];
let data = Data()
do {
try match?.send(data, to: players, dataMode: .reliable)
} catch {
print("Sending failed")
}
}
}
我正在尝试在一个非常简单的游戏中使用 GameKit 将两个玩家相互联系起来。我想使用 GKMatchmaker.shared().findMatch
因为我不想显示任何与 GameCenter 相关的视图控制器。 (为简单起见)
问题:
即使 GameKit 在找到两名玩家后创建了一场比赛,也会发生一个错误,阻止任何一名玩家向其他玩家发送任何消息。
现状:
基本代码如下(基于此处描述的文档:https://developer.apple.com/documentation/gamekit/finding_multiple_players_for_a_game)
print("Requesting multiplayer match")
let request = GKMatchRequest()
request.minPlayers = 2
request.maxPlayers = 2
request.recipientResponseHandler = {(player: GKPlayer, respnse: GKInviteRecipientResponse) -> Void in
print("new player about to join")
print(player.alias)
print(respnse)
}
GKMatchmaker.shared().findMatch(for: request, withCompletionHandler: {
(match: GKMatch?, error: Error?) -> Void in
if error != nil {
// Handle the error that occurred finding a match.
print("error during matchmaking")
print(error as Any)
} else if match != nil {
guard let match = match else { return }
print("connected to \(match.players.count) players")
// load the multiplayer data handler
let handler = MultiMatchHandler()
match.delegate = handler
// load the multiplayer service
let service = MultiMatchService(match: match)
service.sendMessageToAll(text: "Hello from the other side")
// finish the match making
GKMatchmaker.shared().finishMatchmaking(for: match)
// Start the game with the players in the match.
self.view?.presentScene(GameScene.newScene(multiplayer: service))
}
})
那个的输出是
Requesting multiplayer match
2022-01-05 01:19:16.554959+0100 Grapefruit[38300:10026027] [Match] cannot set connecting state for players: (
"<GKPlayer: 0x282add280>(alias:... gamePlayerID:... teamPlayerID:... name:... status:(null) friendBiDirectional:0 friendPlayedWith:1 friendPlayedNearby:0 acceptedGameInviteFromThisFriend:0 initiatedGameInviteToThisFriend:0 automatchedTogether:1)"
), as there is no inviteDelegate set yet. The state might directly change to Ready when we set the inviteDelegate later and call sendQueuedStatesAndPackets.
2022-01-05 01:19:16.557002+0100 Grapefruit[38300:10026027] [Match] syncPlayers failed to loadPlayersForLegacyIdentifiers: (
"..."
)
connected to 0 players
sending text Hello from the other side failed
调查结果:
minPlayers
设置为 2。调用完成处理程序意味着至少找到了一名玩家。但是match.players.count
返回的玩家数是0- 匹配器显示一个错误,指出
cannot set connecting state for players ... as there is no inviteDelegate set yet
。我找不到有关此邀请代表的任何信息。
实际问题:
什么是邀请代表?我真的需要实施这样的(如果是,那么如何实施?)? (我不这么认为,因为文档说明比赛仅在接受邀请后才开始)。
我该如何解决这个问题?
这是一个适合您的工作示例。在两台机器上打开,确保都经过身份验证,在两台机器上按“findMatch()”(并等待确认),然后 ping baby ping
我相信“尚未设置邀请代表”错误并不意味着必要的匹配失败,可以安全地忽略,如前所述here
您需要实现更多 GKMatchDelegate 协议,但这是用于演示目的的框架
import SwiftUI
import GameKit
import SpriteKit
class MyGameScene: SKScene, GKMatchDelegate {
override func didMove(to view: SKView) {
self.backgroundColor = .yellow
}
//GKMatchDelegate protocol
func match(_ match: GKMatch, didReceive data: Data, forRecipient recipient: GKPlayer, fromRemotePlayer player: GKPlayer) {
print("\(Self.self) \(#function) -- ping received")
}
}
struct Matchmaker: View {
@State var isAuthenticated:Bool = false
@State var scene = MyGameScene()
@State var match:GKMatch? = nil
var body: some View {
ZStack {
Color.clear
SpriteView(scene: scene)
VStack(alignment: .leading, spacing: 20) {
Text("1) authenticate() \(Image(systemName: isAuthenticated ? "checkmark.icloud" : "xmark.icloud"))")
Button { findMatch() } label: {
Text("2) findMatch() \(Image(systemName: (match != nil) ? "person.fill.checkmark" : "person.fill.xmark"))")
}
Button { ping() } label: {
Text("3) ping()")
}
}
}
.onAppear() {
authenticate()
}
}
func authenticate() {
GKLocalPlayer.local.authenticateHandler = { viewController, error in
if let error = error { print(error) }
isAuthenticated = (error == nil)
}
}
func findMatch() {
guard isAuthenticated else { return }
let request = GKMatchRequest()
request.minPlayers = 2
request.maxPlayers = 2
request.playerAttributes = 0xFFFFFFFF //mask for "i'll match with anyone"
GKMatchmaker.shared().findMatch (for: request) { match, error in
if let error = error { print(error) }
self.match = match
self.match?.delegate = scene
}
}
func ping() {
let players = match?.players ?? [];
let data = Data()
do {
try match?.send(data, to: players, dataMode: .reliable)
} catch {
print("Sending failed")
}
}
}