iOS マルチプレイヤー GameCenter ゲームを作成しましたが、公開する直前に解決方法がわからない問題が見つかりました。コーディング プロセスでは、Ray Wenderlich チュートリアルを使用しましたhttp://www.raywenderlich.com/3276/how-to-make-a-simple-multiplayer-game-with-game-center-tutorial-part-12
GameCenter ビュー コントローラーが表示されます、接続が作成され、両方のデバイスが同じ Wifi ネットワークに接続されるまでゲームをプレイできます。携帯電話の Wifi をオフにして 3G ネットワークを使用している場合、新しいゲームを開始しようとすると、接続が確立されなくなります。両方のデバイスがお互いを検出しますが、「接続中...」画面でハングします。- (void)match:( GKMatch
*)theMatch player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state
は呼び出されません。それを解決する方法、または少なくとも問題を理解する方法はありますか?
1 に答える
あなたの特定のケースでは、3G ISP が必要なポートからの接続を制限していることが問題だと思います。アップルのドキュメントには次のように書かれています。
Game Center を使用するには、ポート 443 (TCP)、3478 ~ 3497 (UDP)、4398 (UDP)、5223 (TCP)、16384 ~ 16387 (UDP)、および 16393 ~ 16472 (UDP) のポート フォワーディングを有効にする必要があります。
Bluetooth経由でiPhoneに接続されたiPadで再生しようとすると、この問題にも直面しました。各デバイスに「接続中...」画面がありました。しかし、内蔵の iPad 3G (料金プランが異なる) を使用すると、すべて問題なく動作します。
match:player:didChangeState:
通常のマッチメイキング シナリオでは、呼び出されない可能性があることを思い出してください。また、次を確認する必要がありますmatch.expectedPlayerCount
。- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *)theMatch { //... if (theMatch.expectedPlayerCount == 0) { NSLog(@"Ready to start match!"); } }
また、「接続中...」画面でも同様の問題が発生すると予想していましたが、Wifi ネットワーク上で発生しました。そして、
-[GKMatch rematchWithCompletionHandler:^(GKMatch *match, NSError *error) {}]
以前経由で再戦を試みた後、iOS6でのみ再現されました。一方のデバイスは「接続中...」画面でハングしましたが、もう一方のデバイス
matchmakerViewController:didFindMatch:
は正常に呼び出されましたが、興味深いのはmatch.expectedPlayerCount
、0
同時にmatch.playerIDs
配列が空だったことです。前のマッチがバックグラウンドスレッドで再接続しようとしている間に新しいマッチを見つけようとしたため、このようなエラーが発生したと思います。そのため、新しい一致が破損して取得されました。
決定は、rematchCompletionが呼び出されるのを待ってから、新しい一致を見つけようとすることです。
GKMatch
再戦をキャンセルするためのインターフェイスがないため[[GKMatchmaker sharedMatchmaker] cancel]
、数秒後にrematchCompletionが呼び出されてエラーが発生し、新しい一致の検索を開始する準備が整いました。また、使用されていない古い GKMatch インスタンスの割り当てが解除されず、GameKit フレームワークのどこかに存在し続けることもわかりました。また、それらを使用した作業が正しく終了していない場合 (つまり、切断されていないか、私の場合は再戦がキャンセルされていない場合)、おそらく問題が発生する可能性があります。
-[GKMatch disconnect]
そのため、一致オブジェクトへの最後の強い参照を削除する前に、他の種類の作業を呼び出して終了することを忘れないでください。