このページは編集中です。更新が保留になっている可能性があります。
fusion | v1 switch to V2  

6 - リモートプロシージャコール

概要

リモートプロシージャコール(RPC)は、あらゆるネットワークライブラリで最も典型的な機能で、通常メソッドへの直感型マッピングは共通ワールドで複数のクライアントをまとめようとする際に第一候補に挙がるものですが、残念ながら最もいい方法ではないことがしばしばあります。

Fusionのようなティックベース同期ライブラリにおいては、RPCは特定のティックに紐づいておらず様々なクライアント上で、様々なタイミングで実行してしまうため問題を起こす可能性があります。それ以上に、ネットワークステートの一部ではないので、RPCが送信された後に接続または再接続したクライアントや、アンリライアブルで送信されたことにより受信できなかったクライアントは、その結果が表示されないということになります。

ステート同期自体は、多くのケースではプレイヤーの進捗を合わせておくには充分で、ネットワークプロパティへのOnChangeリスナーの追加は、アプリケーションが地齋のステート自体のみでなくステートでの変更も対処する多くの過渡的なケースに対処することができます。

それでも、RPCが良い選択肢となり得る場合もあります。そのようなケースを以下に挙げてみます。

  1. プレイヤー間で挑発的なメッセージやゲームプレイ以外のVolatileなやりとりを送信する場合
  2. タイミングの正確性が重要ではない、ゲーム内ショップからギアを購入する場合で、RPC呼び出しの直接的な結果(資金の差し引きや在庫への追加)がその呼び出しを行ったプレイヤーにのみ重要である場合(つまり、前述の購入にRPCを使用しないこと。)
  3. 名前、色、スキンなど初期プレイヤープロパティを設定する場合。(プレイヤーによる「レア」入力の直接的な結果であるものすべて。基本的には、ティックごとの入力構造に入れたくないプレイヤー入力すべて。)
  4. Lゲームを起動する場合(ゲームモード、マップへの投票、またはプレイヤーの用意が完了していることをホストに通知する場合)

本トピックの詳細についてはこちらを参照してください

トップに戻る
 

Fusion RPC

RPCが選ばれるべきケースにおいては、FusionはRPCをとてもシンプルにします。任意のSimulationBehaviourでコンベンショナルメソッドにRPC属性でタグ付けし、このメソッドを呼び出せる人およびこのコールを受信できる人を通知します。メソッドのプリフィクスまたはポストフィクスに「RPC」が含まれているようにしておきます(大文字小文字は問わない)。これで、メソッドを呼び出す準備ができます。

こちらのミニサンプルでは、R キーを押してその他すべてのプレイヤーに「Hello Mate!」というメッセージを送信することがゴールです。

トップに戻る
 

RPCを呼び出す

RPC自体を追加する前に、入力処理の拡張が必要となります。RPC呼び出しが実際にネットワークメッセージであることから、入力構造を拡張するひつようはありません。また、RPCはティックに準じるものではないので、Fusionの入力処理を行う必要もありません。Player.csを開いて以下を追加してください。:

private void Update()
{
  if (Object.HasInputAuthority && Input.GetKeyDown(KeyCode.R))
  {
    RPC_SendMessage("Hey Mate!");
  }
}

Object.HasInputAuthorityの確認に注意してください。このコードはすべてのクライアント上で実行しますが、このプレイヤーを管理するクライアントのみがこのRPCを呼び出すようにしてください。

トップに戻る
 

RPC実装

Player.cs内に、RPCの本体部分も追加します。[Rpc] 属性と「RPC」で始まるメソッド名でタグが付けられます。以下を参照してください。 :

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

テキストフィールドのサイズを変更して、画面全体に収まるようにすることで読みやすくなります。

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