同期とは
複数台のクライアントPC上で処理のタイミングを合わせることを同期といいます。
同期はオンラインゲームを作る上でとても重要な要素で、必ず理解しておいた方が良いです。
個人的にはオンラインゲームを作る労力の5割くらいはスムーズな同期を行うことに費やしたと思います。
Photonではこの同期を取る方法がいくつかあり、実装したいことに応じてそれらを使い分ける必要があります。
同期
同期の方法については以下のPhoton公式文書ページに詳しく書いてありますが、この記事では分かりやすいように例を交えて説明したいと思います。
同期をとる方法には大きく以下の3つの方法があります。
- Object Synchronization
- RPC(リモートプロシージャーコール)
- カスタムプロパティ
これら全てでクライアントPC間で同期は取ることができますが、それぞれに特徴があります。
その使い分け方と特徴について説明していきます。
同期方法の使い分け方
これらそれぞれを上手く使い分けるためにはどれくらい頻繁に同期を取る必要があるかを考えます。
以下はそれぞれの同期方法の特徴を簡単にまとめた表です。
同期方法 | 特徴 |
Object Synchronization | キャラクターの位置や状態など、頻繁な更新が必要な場合用いる同期方法です。頻繁に同期するので他の同期方法に比べ、通信負荷は高いです。 |
RPC(リモートプロシージャーコール) | ある程度更新頻度の低い、またはユーザーの入力による同期などに適している同期方法です。攻撃や被弾など、特定のタイミングで同期が必要な場合によく使います。 |
カスタムプロパティ | 特定のタイミングかつ更新頻度の低いものの同期に適した方法です。キャラクターが所属するチーム情報などの格納に使ったりできます。 |
では少し例を交えて説明しましょう。
例題 銃の弾丸の同期
例えばFPSのオンラインゲームを作成するとしましょう。
キャラクターが放つ弾丸はプレイヤーの正面に等速直線運動して飛んでいく仕様にしたいとき、どの方法で同期を取ればよいでしょうか?
一見、銃の弾丸の位置は頻繁に変化するのでObject Synchronizationで同期を取る必要があるように思うかもしれません。
しかし良く考えてみると、銃の弾丸はあるタイミングである位置に生成されてある方向に等速直線運動をするオブジェクトです。
つまり銃を撃った瞬間にプレイヤーの位置と正面ベクトルをRPCを用いて同期して弾丸を生成すれば全てのクライアント上であたかもリアルタイムで同期しているような弾丸を実装できます。しかもObject Synchronizationで同期を取るよりも遥かに少ない通信負荷で済みます。
このように同期するオブジェクトの位置や状態が激しく変わる場合でも同期する必要があるタイミングがごく少ない場合もあります。
ではプレイヤーの入力で発射してから操作できるロケットランチャーの弾丸を実装する場合にはどうしたらよいでしょうか?
この場合、RPCで同期しようとするとプレイヤーの入力が入る度に同期を取る必要があり、入力の同期のタイミングもクライアントPC毎でわずかにずれが生じる恐れがあるため適していません。
Object Synchronizationを使ってロケットランチャーの弾丸の位置を同期してやるのが適していると思われます。
最後に
実装したいシステムによって同期の方法はどのようにすべきかは様々だと思いますので、それぞれの特徴を理解してよく考えて実装しましょう。
今後の記事で
- Object Synchronization
- RPC(リモートプロシージャーコール)
- カスタムプロパティ
それぞれについてもまとめていきたいと思いますのでお楽しみに!!