This document is about: FUSION 2
SWITCH TO

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

概要

リモートプロシージャコール(RPC)は、単発のゲームイベントの共有に最適です。一方、入力とネットワークプロパティは、クライアント間で継続的に変化する状態を共有する主力の方法になります。

使用例は、あるプレイヤーが入力権限を持たないオブジェクトに低頻度で複雑なインタラクションを行いたい場合(施錠されたドアを開けるために、インベントリ内の特定の鍵を使用するなど)です。入力に追加のフィールドを含めることで、技術的には同様の操作を達成することもできますが、そうすると入力構造体が乱雑に肥大化してしまいます。

さらに、入力構造体は信頼性のないメッセージで送信されるため、パケットが失われることがあります。継続的な入力(例えばキャラクターの移動)で目立つことはめったにありませんが、確実に実行したい単発のアクションに影響するとユーザー体験を損ねてしまうでしょう。このような状況では、RPCが最善の方法です。

セットアップ

Fusionは、RPCのためのシンプルながら強力な構文を備えています。RPCは大まかに3タイプあります。

  1. インスタンスRPC
  2. 静的RPC
  3. ターゲットRPC

それぞれのタイプを以下で説明していきます。

インスタンスRPC

ネットワークオブジェクトのNetworkBehaviourでRPCを定義するには、以下のステップに従います。

  1. voidまたはRpcInvokeInfo(後述)を返す通常のC#メソッドを宣言する
  2. メソッド名の接頭辞または接尾辞に「RPC」(大文字小文字を区別しない)を付ける
  3. [Rpc]属性をメソッド宣言の前に追加する
  4. RpcSourcesRpcTargetsを設定して、誰がRPCが呼び出し誰がRPCを実行するのかを制御する

C#

[Rpc(sources: RpcSources.InputAuthority, targets: RpcTargets.StateAuthority)]
public void RPC_Configure(string name, Color color){
    playerName = name;
    playerColor = color;
}

静的RPC

静的RPCは、わずかに異なるルールに従います。

  • RpcSourcesRpcTargetsは無視されます
  • メソッドの最初の引数にNetworkRunnerが必要です
  • NetworkBehaviourだけでなく)SimulationBehaviourでも実装可能で、特定のNetworkObjectにはバインドされません

RpcSourcesRpcTargetsが無いため、静的RPCは、どのクライアントでも呼び出し可能で、全てのクライアントに送信されます。ターゲットRPCにすれば、特定のPlayerRefを指定して、誰がRPCを受信するかを制御できます。

C#

[Rpc]
public static void Rpc_MyStaticRpc(NetworkRunner runner, int a) { }

RPC属性のパラメーター

ソースとターゲット

RpcSourcesRpcTargetsはフィルターで、RpcsSourcesはどのピアがRPCを送信できるかを定義し、RpcTargetsはどのピアがRPCを実装するのかを定義します。

  • All:セッション内の全てのピア(サーバー含む)で送信・実行できます
  • Proxies:オブジェクトの入力権限も状態権限も持たないピアで送信・実行できます
  • InputAuthority:オブジェクトの入力権限者で送信・実行できます
  • StateAuthority:オブジェクトの状態権限者で送信・実行できます

重要: RPCは明示的な状態を持ちません。途中参加したクライアントや、一度セッションを切断して再接続したクライアントでは、RPCの実行結果が無視されることがあります。そのため、以下のどちらかの点を保証することが非常に重要です。

  • 本当に一時的なイベントで、状態を持たない(例:チャットメッセージ)
  • 実行結果が間接的にネットワークプロパティに記録される

C#

public class Player : NetworkBehaviour {
    [Networked] public string playerName { get; set; }
    [Networked] public Color playerColor { get; set; }

    [Rpc(RpcSources.InputAuthority, RpcTargets.StateAuthority)]
    public void RPC_Configure(string name, Color color)    {
        playerName = name;
        playerColor = color;
    }
}

オプションのRPC属性のパラメーター

[Rpc]属性はRpcSourcesRpcTargetsに加えて、いくつかのオプションのパラメーターを提供しています。

  • Channel(デフォルトはReliable):Unreliableに設定すると、RPCが送信中に損失することがあります
  • InvokeLocal(デフォルトはtrue):RPCがローカルのクライアントで呼び出されるかどうかを決める
  • InvokeResim(デフォルトはfalse):RPCが再シミュレーション中に呼び出されるかどうかを決める
  • TickAligned(デフォルトはtrue):RPCが送信されたティックに到達するまで、RPCの実行を遅らせたくない場合はfalseに設定する

C#

[Rpc (RpcSources.All, RpcTargets.All, InvokeLocal = true, InvokeResim = true, TickAligned = false )]
void RpcStartBoost(){
    m_BoostAnim.StartBoostAnimation();
}

RPCメソッドのパラメーター

RPCは実行時にシリアライズされるので、Fusionのデータ型(例:NetworkBool)ではなく、通常のCLRの型(例:bool)の使用を推奨します。

有効なデータ型

  • Primitives
    • byte, sbyte
    • Int16, Int32, Int64
    • UInt16, UInt32, UInt64
    • float
    • double
    • float
    • double
  • Unity struct types (defined in ILWeaver.cs)
    • Vector2, Vector3, Vector4
    • Quaternion
    • Matrix4x4
    • Vector2Int, Vector3Int
    • BoundingSphere
    • Bounds
    • Rect
    • BoundsInt
    • RectInt
    • Color, Color32
  • System.Guid
  • User Defined INetworkStructs
  • Fusion Defined INetworkStructs
    • NetworkString<IFixedStorage>
    • NetworkBool
    • Ptr
    • Angle
    • BitSet64, BitSet128, BitSet192, BitSet256
    • PlayerRefSet
    • NetworkId
    • NetworkButtons
    • NetworkRNG
    • NetworkObjectGuid
    • NetworkPrefabRef
    • NetworkObjectHeader
    • NetworkPrefabId
    • SceneRef
    • TickTimer
    • IFixedStorage (_2, _4, _8, _16, _32, _64, _128, _256, _512)
  • Fusion Types
    • NetworkObject (serialized as NetworkId)
    • NetworkBehaviour (serialized as NetworkId and the NetworkBehaviour index)
    • PlayerRef (serialized as PlayerRef.PlayerId)
  • Strings
  • Arrays of any of the types listed above

RpcInfo

RPCメソッドの宣言では、オプションでRpcInfo型をパラメーターを追加できます。RpcInfoは、以下のようなRPCのメタ情報を公開します。

  • Tick:RPCが送信されたティック
  • Source:送信したプレイヤー(PlayerRef
  • ChannelUnreliableまたはReliableのどちらでRPCが送信されたか
  • IsInvokeLocal:RPCを呼び出したのがローカルプレイヤーかどうか

C#

[Rpc(sources: RpcSources.InputAuthority, targets: RpcTargets.StateAuthority)]
public void RPC_Configure(string name, Color color, RpcInfo info = default){
    playerName = name;
    playerColor = color;
}

パラメーターは必ずRpcInfo info = defaultで宣言してください。

サーバーモードとホストモードのソース

サーバーモードでは、サーバーが送信するRPCのRpcInfo.SourcePlayerRef.Noneに設定されます。サーバーはプレイヤーではないためです。

ホストモードでは、ホストはサーバーとプレイヤーを兼ねています。デフォルトでは、ホストはRPCをサーバーとして送信するので、RpcInfo.SourcePlayerRef.Noneに設定されます。ここにホストのローカルのPlayerRefを含めたい場合は、HostMode属性をRpcHostMode.SourceIsHostPlayerに設定する必要があります。

ホストモードでは、以下の2つのモードのうちの1つを設定できます。

  • RpcHostMode.SourceIsServer(デフォルト):RpcInfo.SourcePlayerRef.Noneに設定されます
  • RpcHostMode.SourceIsHostPlayerRpcInfo.SourceはローカルのPlayerRefに設定されます(ホストモード時)

先ほどのスニペットのRpcSource.Infoに、ホストのPlayerRefを含めるように調整すると、以下のようになります。

C#

[Rpc(sources: RpcSources.InputAuthority, targets: RpcTargets.StateAuthority, HostMode = RpcHostMode.SourceIsHostPlayer)]
public void RPC_Configure(string name, Color color, RpcInfo info = default){
    playerName = name;
    playerColor = color;
}

RpcInvokeInfo

RPCメソッドは、オプションでRpcInvokeInfoを戻り値にできます。RPCメソッドを呼び出すと、RPCの呼び出しと送信処理に関する情報を含むRpcInvokeInfoが返ります。

  • LocalInvokeResultRpcLocalInvokeResultのenum値(ローカルのRPC呼び出しの成否を示す)
  • SendCullResultRpcSendCullResultのenum値(リモートのRPC呼び出しの成否を示す)
  • SendResultRpcSendResult構造体(RPC送信処理のメタ情報を含む)
    • ResultRpcSendMessageResult(RPC送信処理の結果フラグ)
    • MessageSize:RPCのパッケージサイズ
    • Receivers:RPCの受信対象に含まれるPlayerRefのコレクション
    • CulledReceivers:RPCの受信対象から除外されたPlayerRefのコレクション

注意: これは「到達(対象に届いたか)」の成否情報ではなく、「呼び出し」と「送信」処理の結果情報です。

C#

[Rpc]
public RpcInvokeInfo RpcFoo() {
  // RPC action
  return default;
}

public override void FixedUpdateNetwork() {
  var info = RpcFoo();
  Debug.Log(info);
}

ターゲットRPC

ターゲットRPCは、特定のプレイヤーでのみRPCを実行したい場合に使用します。[RpcTarget]属性で始まるPlayerRefパラメーターを追加することで、インスタンスRPCも静的RPCもどちらも、ターゲットRPCにすることができます。典型的なユースケースはチームチャットで、自身が所属するチームの特定のプレイヤーのみに向けてメッセージを送ることができます。

注釈: [RpcTarget]PlayerRef.Noneを渡すと、サーバーが対象になります!

C#

[Rpc(sources: RpcSources.InputAuthority, targets: RpcTargets.All)]
public void Rpc_TargetedInstanceMessage([RpcTarget] PlayerRef player, string message){}

または

C#

[Rpc(sources: RpcSources.InputAuthority, targets: RpcTargets.All)]
public static void Rpc_MyTargetedStaticMessage(NetworkRunner runner, [RpcTarget] PlayerRef player, string message) { };

重要: メソッド宣言の中で使用する[RpcTarget]属性と、メソッド宣言の前に追加する[Rpc]属性のRpcTargetsパラメーターは、別物です。

Back to top