UNET⑤ たくさんある情報の送信方法の解説
UNETに用意された数々の情報の送信方法について、概要を説明します。
前回、NetworkManagerを使って、複数のゲームを接続しましたが、ゲーム内のキャラクターなどを同期して動かすためには、「キャラクターを動かしたいですよー」とか「キャラクターを動かしましたよー」とかそういう情報を端末間で送信しあわないといけません。その方法がUNETにはたくさん用意されています。状況と好みに応じて、好きなものが使えるのですが、たくさん用意されすぎていて、これがまた初学者を混乱させます。
以下でそれぞれの概要を説明します。
Command
Commandとは、クライアントからサーバー(ホスト)の関数を呼び出す機能です。何らのイベントのトリガーとして使うことも出来るし、引数も渡せるので、情報の送信に使うことも可能です。
例えば、「今、弾撃ちました!」とか「今ここに移動しました!」とかそういう情報をサーバーに伝えるのに使います。
注意しなければならないのは、Commandで送信できるのはクライアントからサーバーに対してだけで、クライアントに対してCommandを送信することは出来ません。とにかく、Commandとはサーバーの関数を呼ぶ機能だと覚えてください。
ClientRPC
ClientRPCとは、サーバーからクライアントの関数を呼び出す機能です。
情報の流れとしては完全にCommandの逆です。
ClientRPCを使うと、全クライアントで一斉に関数が呼び出されます。
TargetRPC
ClientRPCは全クライアントの関数を一斉に呼び出す機能でしたが、TargetRPCは、対象を1つのクライアントのみに絞ったものです。それ以外はClientRPCと同じです。
SyncVar
SyncVarは変数を同期する機能です。サーバー上の変数の変化をクライアントに配信して同期します。
注意しなければならないのは、情報伝達の方向は常に
サーバー → クライアント
であり、逆は出来ないということです。変数をクライアント側で変更しても、その変更はサーバーおよび他クライアントには届きません(そのようなことがしたい場合はCommandを使います)。
int, float, stringなどのプリミティブな型が同期可能です。Vector3などのUnity組み込み型、自作の構造体も同期可能です。自作のクラスは同期できません。
SyncList
SyncVarでは、配列やListの同期はできません。そういったものの同期をしたい時に使うのがこのSyncListです。データの流れなどの特徴はSyncVarと同じです。
Message
サーバーとクライアントの間で自由にメッセージを送信します。
サーバー→クライアントの方向も
クライアント→サーバーの方向も使えます。
※クライアント→クライアントはできないので注意。
単純なイベント通知としても使えますし、データの受け渡しにも使えます。非常に汎用性の高い機能です。
ただし、CommandやClientRPCと比べると、使うのが面倒です。メッセージのIDを定義したり、「このメッセージIDを受信したらこの関数を呼び出してね」っていう登録をあらかじめ行う必要があります。
SyncEvent
サーバー側でイベントを発行すると、クライアント側でイベントハンドラの関数が実行される機能です。ClientRPCと似たような働きをします。こちらはC#のeventなので、ClientRPCと違うのは、ゲーム実行時に動的に関数を登録するということと、複数登録できるということでしょうか。
ClientRPCより使用法が煩雑なわりにメリットが少ないため、この機能の存在意義がよくわからなくて結構悩んだのですが、実際、Unityの中の人も「あまり有用ではない」と言っているのを発見して、ガックシきました。
まあ覚えなくて良い機能かと。
NetworkTransform
キャラクターなどのオブジェクトの位置と向きを同期するための機能です。
これを使えば手軽に位置情報の同期が実現しますが、0コンマ何秒といったラグすら許容できないというシビアなゲームを作る場合は、NetworkTransformに頼らず、位置の同期の仕組みを自作する必要があります。ネットワーク越しに送られてきた位置情報は、どう頑張っても古い情報ですから、その古い情報から現在の位置を推測して表示するなどの工夫でごまかします(未来予測みたいなもんです)。