リモートプロシージャコール
概要
リモートプロシージャコール(RPC)は、単発のゲームイベントの共有に最適です。一方、入力とネットワークプロパティは、クライアント間で継続的に変化する状態を共有する主力の方法になります。
使用例は、あるプレイヤーが入力権限を持たないオブジェクトに低頻度で複雑なインタラクションを行いたい場合(施錠されたドアを開けるために、インベントリ内の特定の鍵を使用するなど)です。入力に追加のフィールドを含めることで、技術的には同様の操作を達成することもできますが、そうすると入力構造体が乱雑に肥大化してしまいます。
さらに、入力構造体は信頼性のないメッセージで送信されるため、パケットが失われることがあります。継続的な入力(例えばキャラクターの移動)で目立つことはめったにありませんが、確実に実行したい単発のアクションに影響するとユーザー体験を損ねてしまうでしょう。このような状況では、RPCが最善の方法です。
RPCの作成
ネットワークオブジェクトのNetworkBehaviour
でRPCを定義するには、以下のステップに従います。
void
またはRpcInvokeInfo
(後述)を返す通常のC#メソッドを宣言する- メソッド名の接頭辞または接尾辞に「RPC」(大文字小文字を区別しない)を付ける
[Rpc]
属性をメソッド宣言の前に追加するRpcSources
とRpcTargets
を設定して、誰がRPCが呼び出し誰がRPCを実行するのかを制御する
C#
[Rpc(sources: RpcSources.InputAuthority, targets: RpcTargets.StateAuthority)]
public void RPC_Configure(string name, Color color){
playerName = name;
playerColor = color;
}
RPCを動作させるには、メソッド名の接頭辞か接尾辞に「RPC」を付ける必要があります。
静的RPC
静的RPCは、わずかに異なるルールに従います。
RpcSources
とRpcTargets
は無視されますメソッドの最初の引数に
NetworkRunner
が必要です(
NetworkBehaviour
だけでなく)SimulationBehaviour
でも実装可能で、特定のNetworkObject
にはバインドされません
RpcSources
とRpcTargets
が無いため、静的RPCは、どのクライアントでも呼び出し可能で、全てのクライアントに送信されます。ターゲットRPCにすれば、特定のPlayerRef
を指定して、誰がRPCを受信するかを制御できます。
C#
[Rpc]
public static void Rpc_MyStaticRpc(NetworkRunner runner, int a) { }
RPC属性のパラメーター
ソースとターゲット
RpcSources
とRpcTargets
はフィルターで、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]
属性はRpcSources
とRpcTargets
に加えて、いくつかのオプションのパラメーターを提供しています。
Channel
(デフォルトはReliable
):Unreliable
に設定すると、RPCが送信中に損失することがありますInvokeLocal
(デフォルトはtrue
):RPCがローカルのクライアントで呼び出されるかどうかを決めるTickAligned
(デフォルトはtrue
):RPCが送信されたティックに到達するまで、RPCの実行を遅らせたくない場合はfalse
に設定する
C#
[Rpc (RpcSources.All, RpcTargets.All, InvokeLocal = true, TickAligned = false )]
void RpcStartBoost(){
m_BoostAnim.StartBoostAnimation();
}
RPCメソッドのパラメーター
RPCは実行時にシリアライズされるので、Fusionのデータ型(例:NetworkBool
)ではなく、通常のCLRの型(例:bool
)の使用を推奨します。
有効なデータ型
RPCは、以下のデータ型に対応しています。
- 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 theNetworkBehaviour
index) - PlayerRef (serialized as
PlayerRef.PlayerId
)
- NetworkObject (serialized as
- Strings
- Arrays of any of the types listed above
RpcInfo
RPCメソッドの宣言では、オプションでRpcInfo
型をパラメーターを追加できます。RpcInfo
は、以下のようなRPCのメタ情報を公開します。
Tick
:RPCが送信されたティックSource
:送信したプレイヤー(PlayerRef
)Channel
:Unreliable
または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.Source
はPlayerRef.None
に設定されます。サーバーはプレイヤーではないためです。
ホストモードでは、ホストはサーバーとプレイヤーを兼ねています。デフォルトでは、ホストはRPCをサーバーとして送信するので、RpcInfo.Source
はPlayerRef.None
に設定されます。ここにホストのローカルのPlayerRef
を含めたい場合は、HostMode
属性をRpcHostMode.SourceIsHostPlayer
に設定する必要があります。
ホストモードでは、以下の2つのモードのうちの1つを設定できます。
RpcHostMode.SourceIsServer
(デフォルト):RpcInfo.Source
はPlayerRef.None
に設定されますRpcHostMode.SourceIsHostPlayer
:RpcInfo.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
が返ります。
LocalInvokeResult
:RpcLocalInvokeResult
のenum値(ローカルのRPC呼び出しの成否を示す)SendCullResult
:RpcSendCullResult
のenum値(リモートのRPC呼び出しの成否を示す)SendResult
:RpcSendResult
構造体(RPC送信処理のメタ情報を含む)Result
:RpcSendMessageResult
(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
パラメーターは、別物です。