接続が切断された場合の調査

オンラインマルチプレイヤーゲームを構築する際には、クライアントとサーバー間の接続が失敗する場合を想定しておく必要があります。

切断の原因は、ソフトウェアまたはハードウェアです。 接続のいずれかのリンクが失敗すると、メッセージの遅延や、欠落、破損が発生し、接続をシャットダウンしなければなりません。

切断が頻繁に起きる場合は、以下の解決策を試してみてください。

よくある問題

タイムアウトによる切断

タイムアウトによる切断は「まったく」接続できない問題を除けば、もっとも多く発生する問題です。

タイムアウトとは、確立された接続が高信頼性のメッセージの送信や確認に失敗し、接続が閉じられたことを意味します。

Photon接続の両側(クライアントとサーバ)は、送信した高信頼性コマンドが相手側に確認されたかを監視します。 (現在のラウンドトリップタイムを基準にして)「すぐに」ACKがない場合、高信頼性コマンドは再送されます。

数回繰り返しても反応がない場合には、相手側が正常に応答できないとみなされ接続はタイムアウトされます。

タイムアウトの処理

頻繁にタイムアウトが発生する場合、障害の発生箇所は1つではありません。問題の原因として考えられるシナリオや、修正方法は複数あります。

頻繁にタイムアウト切断が発生するならば、送信するデータの量を確認する必要があります。 データ量の急増がある場合、またはメッセージ/秒率が非常に高い場合は接続の品質に影響します。

他のハードウェア上や別のネットワーク上でその問題を再現できるか、確認してください。

再送の回数とタイミングを調整することができます。 「解決策:再送信を微調整」を参照してください。

再送信された高信頼性コマンドを確認する」を参照してください。

トラフィックの問題とバッファフル

バッファフルの問題は、「メモリ不足」の問題に似ています。 Photon Serverとクライアントは、実際にパッケージされインターネット経由で送信される前に、通常はいくつかのコマンドをバッファします。 これにより複数コマンドを(より少ない)パッケージに集約できるようになります。

いずれかの側が大量のコマンドを発生した場合(たとえば、大きなイベントを大量に送信するなど)、バッファ不足になる可能性があります。

バッファを充填すると、さらにラグが生じる原因になります: イベントが反対側に受信されるまでに、通常より長く時間がかかることがわかります。 また、オペレーションのレスポンスが通常よりも遅くなります。

緊急処置

ログを確認する

これは、最初に確認すべき事項です。

すべてのクライアントには、内部ステートの変化や問題についてのログメッセージを提供する、なんらかのコールバックがあります。 これらのメッセージのログを作成し、問題が発生した場合にはログにアクセスしてください。

有用な情報が表示されない場合には、ロギングを増加することができます。 ロギングを増加させる方法は、APIリファレンスを確認してください。

サーバーをカスタマイズしている場合には、そのサーバーのログを確認してください。

別のプロジェクトを使用

PhotonのすべてのクライアントSDKには、複数のデモが含まれています。 これらの中から、対象となるプラットロームのデモを使用してください。 デモが失敗する場合には、接続に問題が生じている可能性があります。

別のサーバーまたはリージョンを使用

Photon Cloudを使用している場合には、別のリージョンを簡単に使用できます。

独自にホスティングをおこなう際は、仮想マシンではなく物理マシンを使用しましょう。 サーバーに近いクライアント(ただし同一マシン上やネットワーク上ではなく)で最小ラグ(ラウンドトリップタイム)をテストしましょう。 顧客の近くにサーバーを追加する事も検討してみてください。

別の接続を使用

特定のハードウェアが原因で接続に失敗する場合があります。 他のWifiやルーターなどを試してみてください。 別のデバイスで作動状況が改善するか確認してください。

代替のポート番号を使用

2018年初めからPhoton Cloudのすべての実装で、新しいポート番号の範囲をサポートしています: 新しいポート番号の範囲は5055から5058を使用せず、27000から開始します。

ポートを変更しても違いがないように思えるかもしれませんが、実際には非常に効果的です。 現時点では、とても高い評価のフィードバックをいただいています。

一部のクライアントSDKでは、サーバーから受信するアドレス文字列の番号を置換する必要があります。 ネームサーバーは27000 (旧5058)、マスターサーバーは27001 (旧5055)、ゲームサーバーは27002 (旧5056)へと変更されました。 文字列を置換すれば設定が完了します。

CRC Checkを有効化

クライアントとサーバー間でパッケージが破損する場合があります。 ルーターまたはネットワークが非常にビジーな状態の場合に、こうした破損が生じる可能性が高まります。 またハードウェアやソフトウェアによってはバグが多く、破損が発生する可能性が十分にあります。

PhotonにはオプションでパッケージごとのCRC Checkがあります。 パフォーマンス上の問題が生じるため、デフォルトでは有効化されていません。

この機能を使用するには、クライアントでCRC Checkを有効化してください。 ただし有効化した場合にはサーバーもCRCを送信します。

loadBalancingClient.loadBalancingPeer.CrcEnabled = true

Photonクライアントは、CRC Checkの有効化によって何個のパッケージが欠落したかをトラッキングします。

Check:

LoadBalancingClient.loadBalancingPeer.PacketLossByCrc

微調整

トラフィックの統計を確認する

一部のクライアントプラットフォームでは、Photonで直接Traffic Statisticsを有効化できます。 トラフィックの統計では、様々なパフォーマンスインジケーターがトラッキングされ、ログを容易に作成できます。

トラフィックの統計は、C#ではLoadBalancingPeerクラス内のTrafficStatsGameLevelプロパティとして利用可能です。 このプロパティによって興味深い値を参照できます。

たとえば、TrafficStatsGameLevel.LongestDeltaBetweenDispatchingを使用して連続するDispatchIncomginCommandsコール間の最長の間隔を確認してください。 もしこの間隔が数ミリ秒以上ならば、ローカルラグが発生している可能性があります。 LongestDeltaBetweenSendingを参照して、クライアントが頻繁に送信しているか確認してください。

TrafficStatsIncomingプロパティとTrafficStatsOutgoingプロパティは、送受信されるバイトやコマンド、パッケージについてより詳細な統計を提供します。

解決策:再送信を微調整

QuickResendAttempts and SentCountAllowance. 最新のDotNet Photonライブラリには再送信のタイミングを微調整する2つのプロパティがあります: QuickResendAttemptsSentCountAllowanceです。

QuickResendAttemptsは、受信側が確認できない高信頼性コマンドを速く繰り返します。結果として、いくつかのメッセージが欠落した場合にトラフィックが少し増加し、遅延が短くなります。

SentCountAllowanceは、クライアントが個別の高信頼性メッセージをどれくらいの頻度で繰り返すかを定義します。 クライアントが速く繰り返すならば、SentCountAllowanceもより高い頻度で繰り返す必要があります。

QuickResendAttemptsを3に、SentCountAllowanceを7に設定することで状況が改善する場合があります。

再送信された高信頼性コマンドを確認する

ResentReliableCommandsの監視を開始する必要があります。

このカウンターは高信頼性コマンドが送信されるたびに増加します(サーバーからの確認が時間内に受信されなかったため)。

LoadBalancingClient.ResentReliableCommands

もしこの値が上限を超えると接続は不安定になり、パケットは正常に送信されません(どちらの方向にも)。

解決策:送信量を減らす

トラフィックの問題を避けるには、送信量を減らします。 送信量を減らすには、いくつかの方法があります:

必要以上に送信しない

必要な分だけ通信してください。 関連する値のみを送信し、それらの値から出来る限り派生させてください。

状況に応じて、送信するものを最適化してください。 何を送信するべきか、また送信頻度を考慮するようにしましょう。 重要でないデータは同期によって強制的に再計算される場合を除き、同期されたデータ、またはゲームの進行内容にもとづいて受信側で再計算されるべきではありません。

例:

  • RTSでは、発生時に複数のユニット向けに「オーダー」を送信できます。 これは1秒間に10回の頻度で各ユニットに位置、回転、速度を送信するよりもはるかに効率的です。

    1500 archersを参照してください。

  • シューティングゲームでは、発射は位置と方向として送信してください。 銃弾は通常、直線で飛びます。このため、100ミリ秒ごとにそれぞれの位置を送信する必要はありません。 銃弾が何かに当たった場合、または銃弾が「非常に多くの」ユニットを通過した後には、銃弾をクリーンアップすることができます。

  • アニメーションは送信しないでください。通常は、プレイヤーの入力やアクションからすべてのアニメーションを派生することができます。 アニメーションを送信すると遅延が発生する可能性が十分にあり、プレイが遅延すると非常に不自然な印象を与えます。

  • デルタ圧縮を使用してください。前回の送信から変更があった値のみを送信してください。 受信側での値を平滑化するため、データ補間を使用してください。 この方法は無理に同期をおこなうよりも望ましく、トラフィックを軽減します。

送信量を抑える

やり取りする型とデータ構造を最適化してください。

例:

  • 小さな整数の場合には、intではなくbyteを使用してください。可能であれば、floatではなくintを使用してください。
  • stringのやり取りを避け、なるべくenumやbyteを使用してください。
  • 送信されるものが明確でない限り、カスタムの型をやり取りしないでください。

静的なデータ、またはよりサイズの大きなデータをダウンロードするには、別のサービスを使用してください(例:マップ)。

Photonはコンテンツ配信システムとして構築されていません。 HTTPベースのコンテンツシステムを使用したほうがコストを抑えられ、管理も容易です。 最大転送単位(MTU)よりも大きなものはすべて分割され、複数の信頼性の高いパッケージとして送信されます(完全なメッセージへと再構成する必要があります)。

送信頻度を抑える

  • 送信レートを下げてください。できれば、10未満に下げることを推奨します。 この設定は、当然のことながらゲームプレイに応じて異なります。 この変更はトラフィックに大きく影響します。

ユーザーのアクティビティや、やり取りするデータにもとづいて、適応送信レートや動的送信レートを使用できます。この設定もトラフィックに大きく影響します。

  • 可能な場合には信頼性を低くして送信してください。 新たなアップデートをすぐに送信する必要がある場合、通常は信頼性の低いメッセージを使用できます。 信頼性の低いメッセージは、繰り返しを発生しません。 例:FPSでは、通常プレイヤーの位置は信頼性を低くして送信されます。

解決策:定期的にサービスを呼び出す

クライアント側では、接続を維持するため定期的にServiceを呼ぶ必要があります。 1秒間に10~50コールが適切です。

切断の問題やラグが生じた場合にはサービス、またはSendOutgoingCommands()DispatchIncomingCommands()の組み合わせを頻繁に呼び出していることを確認してください。 通常、フレームレートの低下もPhotonの接続に影響します。

Unityではシーンやアセットの読み込み中や、スタンドアロンのプレイヤーのウィンドウのドラッグ中はUpdate()が呼ばれない点に留意してください。

トラフィックの統計が利用可能な場合には、送受信やディスパッチの頻度についての統計情報を取得する必要があります。以下を参照してください。

より低いMTUを試す

クライアント側で設定すれば、通常よりも最大パッケージサイズを小さくしてサーバーやクライアントで使用することができます。 MTUを低くするとメッセージ送信の際により多くのパッケージが必要ですが、他の方法でも改善しない場合にはこの方法を試してみてください。

この方法の結果について弊社では確認できていませんので、状況が改善したかどうかぜひお知らせください。

loadBalancingClient.loadBalancingPeer.MaximumTransferUnit = 520;

繰り返す回数を増やす

デフォルトでは、Photonクライアントはそれぞれの高信頼性コマンドを6回まで送信します。 5回再送信してもACKがない場合、接続は閉じられます。

を設定すれば、試すことができます。

LoadBalancingClient.loadBalancingPeer.SentCountAllowance

繰り返しを増やすことで、接続状況が改善されるとは限りません。また、遅延がより長くなる可能性があります。

ツール

Wireshark

このネットワークプロトコルアナライザーおよびロガーは、ゲームのネットワークレイヤーの状況を把握するのに非常に有用です。 このツールを使用すると、ネットワークの観点から詳細な状況が分かります。

Wiresharkは複雑そうに思えますが、実際にはゲームのトラフィックのログは非常に簡単な設定で取得できます。

インストールして起動します。 最初のツールバーアイコンから(ネットワーク)インターフェースのリストを開きます。

PhotonServerSettings in Inspector
Wireshark Toolbar

トラフィックのあるインターフェースの横のボックスにチェックマークをつけます。 不明な場合には、複数のインターフェースのログを取得してください。 次に「Options」をクリックします。

PhotonServerSettings in Inspector
Wireshark - Capture Interfaces

すべてのネットワークトラフィックは必要ではないため、チェックマークをつけたインターフェースごとにフィルタを設定する必要があります。 次のダイアログボックス(「Capture Options」)で、チェックマークをつけたインターフェースをダブルクリックします。 「Interface Settings」ダイアログボックスが開きます。 ここでフィルタを設定できます。

PhotonServerSettings in Inspector
Wireshark - Interface Settings

Photonに関するログを取得するフィルタは以下の通りです:

(udp || tcp) && (port 5055 || port 5056 || port 5057 || port 5058 || port 843 || port 943 || port 4530 || port 4531 || port 4532 || port 4533 || port 9090 || port 9091 || port 9092 || port 9093 || port 19090 || port 19091 || port 19093 || port 27000 || port 27001 || port 27002)

「Start」を押すと、接続後にロギングが開始されます。 問題を再現できたらロギングを停止し(ツールバーの3番目のボタン)保存します。

何をおこなったのか、そしてエラーが定期的に発生する場合には発生頻度や発生日時(ログにはタイムスタンプがあります)も記載してください。 クライアントソースログも添付してください。

.pcapやその他のファイルをメールで送信いただければ、弊社で調査をおこないます。

 ドキュメントのトップへ戻る