6 - リモートプロシージャコール
概要
リモートプロシージャコール(RPC)は、あらゆるネットワークライブラリで共通した機能です。直感的に通常のメソッドのように使えるため、共有されたワールドの中で複数のクライアントを動かす際の最もお手軽な方法となりますが、残念ながら最良の方法ではないこともあります。
Fusionのようにティックベースの状態同期ライブラリにおいては、RPCは特定のティックに紐づいておらず、クライアントごとに異なるタイミングで実行されることがあるため、問題になる可能性があります。それ以上に、RPCはネットワーク上の状態に含まれないので、RPCが送信された後に接続または再接続したプレイヤーや、到達保証なしで送信されたRPCを受信できなかったプレイヤーには、その結果が表示されることはありません。
大抵のケースでは、プレイヤー間の状態を同期するだけで、ネットワークプロパティにOnChanged
リスナーを追加すれば、実際の状態だけではなく状態の変更を検出することもできるので、それで十分に対処することができます。
それでも、RPCが良い選択肢となり得る場合もあります。そのようなケースを以下に挙げてみます。
- メッセージの送信などゲームプレイに影響しないプレイヤー間のインタラクション
- ゲーム内ショップからのアイテムの購入など、実行タイミングが重要ではなく、RPC呼び出しの直接的な結果(資金の減少、インベントリへアイテムを追加)がその呼び出しを行ったプレイヤーでのみ重要な場合(言い換えると、アイテムの装備にRPCを使うべきではない)
- 名前、色、スキンなどプレイヤーの初期設定(プレイヤーの稀な入力の直接的な結果・ティックごとの入力構造体に含めたくないあらゆるプレイヤー入力)
- ゲームの起動(ゲームモードやマップの投票、または各プレイヤーによるホストへの準備完了の通知)
FusionのRPC
RPCが適切な選択となる少数のケースにおいて、FusionのRPCの実装は非常にシンプルです。任意のNetworkBehaviour
の通常メソッドに[Rpc]
属性を付けて、誰がメソッドを送信して誰がメソッドを受信するかを示します。メソッド名のプレフィックスかサフィックスに「RPC」(大文字と小文字を区別しない)を付けたことを確認したら、RPCを呼び出す準備は完了です。
ここからは、R
キーを押すと自分以外のプレイヤーに「Hello Mate!」というメッセージを送信する小さなサンプルを作成することを目的とします。
RPCを呼び出す
RPCを追加する前に入力処理の追加が必要ですが、RPCは実際のネットワーク上のメッセージになるので入力構造体を修正する必要はありませんし、RPCはティックに紐づいていないのでFusionの入力処理を使用する必要もありません。Player.cs
を開いて以下を追加してください。
C#
private void Update()
{
if (Object.HasInputAuthority && Input.GetKeyDown(KeyCode.R))
{
RPC_SendMessage("Hey Mate!");
}
}
Object.HasInputAuthority
の確認に注意してください。このコードはすべてのクライアントで実行されますが、RPCを呼び出すのはこのプレイヤーを操作するクライアントのみになります。
RPCの実装
Player.cs
内に、RPCの本体部分も追加します。以下のように、[Rpc]
属性と「RPC」で始まるメソッド名を付けてください。
C#
private Text _messages;
[Rpc(RpcSources.InputAuthority, RpcTargets.All)]
public void RPC_SendMessage(string message, RpcInfo info = default)
{
if (_messages == null)
_messages = FindObjectOfType<Text>();
if(info.IsInvokeLocal)
message = $"You said: {message}\n";
else
message = $"Some other player said: {message}\n";
_messages.text += message;
}
RPCSources.InputAuthority
パラメータとRPCTargets.All
パラメータが、入力権限のあるクライアントのみがこのメソッドの呼び出しを行い、全クライアントで実行することを許可するようにFusionへ通知します。
コード自体はシーン内のテキストフィールドを検索してそこにメッセージを貼り付けます。これをテストするために、テキストコンポーネントを追加してください。
GameObject > UI > Text
テキストフィールドのサイズを変更して、画面全体に収まるようにすることで読みやすくなります。
Back to top