読者です 読者をやめる 読者になる 読者になる

通信対戦

完全な同期について真剣に考え出したところで、今までとは違うアプローチの、より良いかもしれない方法を思いついた。


・クライアント側は、常にゲーム内時間をサーバー側とは20フレームくらい遅らせて進行させる。(20フレームは適当。クライアントとの通信速度を元に適切な数値に設定するのが理想)
・やりとりする情報はマウスやキーボードの操作から起こったイベントのみ。(また、そのイベントが起きた時間も情報に含める)
・サーバー側は、クライアントからイベントがきたら受信した瞬間にそれを実行する。
・クライアント側は、サーバーから来たイベントは未来で起こるものであるはずなので、受信したら一旦それをキューに突っ込んでおき、実行すべき時が来たときに実行する。サーバーから来た情報が既に過去のものなら、同期エラーと見なす。
・これでサーバー/クライアントで常に同じ時間に同じイベントが実行されるはず。各プレイヤーがローカルで起こすイベントに乱数が関わらない限り、1フレーム単位での完璧な同期が実現できるはず。


通信が必要な情報はごく僅かでよくなり、完璧な同期が実現できる。要するに一度考えて諦めていた「クライアントもサーバーとは別にゲームの内部計算をやる」系の方法。

で、今のところ考えられる問題点。
何よりも同期エラーが付きまとうこと。例えば上記の例だと通信が20フレーム以上遅れると同期エラーになり、サーバー側の全てのオブジェクトの状態をコピーして完全に戻さない限り同期し直すのが不可能になってしまう。というか復帰は現実的ではない。
次に何らかの方法で同期チェックをやらないといけない点。例えばCOMが混じったゲームでCOMのアルゴリズムが違うプレイヤーがいるとか、ユニットの作成にかかる資源が違うプレイヤーがいるとかの場合(バージョンの違いとかで引き起こされる)、そこで同期エラーが起こる可能性がある。
あとは操作が反映されるのに余分に時間がかかる点。まあAoE系もえらく遅いし、些細な問題。


AoCやAoMで稀に起こる同期エラーは、俺が今まで実装しようとしていた方法では存在し得ない。元々1フレーム単位で完璧に同期することは放棄してる方法なのだ。
だけど、今考えるとAoEシリーズの操作が反映されるまでの時間は長すぎる気がするし、同期エラーなんてもんもあるし、しかも同期エラーが起こる条件は大体上で想定してるのと同じ状況だし、上記の方法と似たような方法を取っている可能性は高いと思われる。


…というわけで、クライアントがローカルでイベント出すのを根絶したばかりで気が重かったりしなくもないけど、上記の方法を試してみることにした。