5 - RPC
概要
前章では、プレイヤーの色を他のプレイヤーと同期するネットワークプロパティを追加しました。そこでは、状態権限を持つプレイヤーが、ネットワークプロパティにした色の値を直接更新していました。
しかし、NetworkObject
の状態権限が他のクライアントにある場合、ネットワークプロパティを直接更新することはできません。
この章では、プレイヤーを攻撃してヘルスを減らす例を通して、他のプレイヤーのネットワークプロパティを変更する方法を説明します。
他のプレイヤーのネットワークプロパティの変更
他のクライアントが状態権限を持つオブジェクトのネットワークプロパティを変更するには、オブジェクトの状態権限を持つクライアントにRPC(リモートプロシージャコール)を送信して、そのクライアントにネットワークプロパティを変更してもらいます。
(状態権限を持たないオブジェクトの)ネットワークプロパティを直接変更することは可能ですが、その更新はローカルのみで適用され、ネットワーク上では同期されません。
今回は、(レイキャストの)武器を持ったプレイヤー同士のシューティングゲームを例にします。共有モードでこれをシンプルに実装する方法は、プレイヤーがローカル上でレイキャストを行い、ターゲットに当たったら、そのターゲットにダメージを与えることです。ホストモードではレイキャストのアプローチが異なりますので、注意してください。
新規スクリプトを作成し、名前をHealth
にします。ネットワークプロパティと、ヘルスの変更を検出するメソッドを追加してください。
C#
using Fusion;
using UnityEngine;
public class Health : NetworkBehaviour
{
[Networked, OnChangedRender(nameof(HealthChanged))]
public float NetworkedHealth { get; set; } = 100;
void HealthChanged()
{
Debug.Log($"Health changed to: {NetworkedHealth}");
}
}
次に、射撃側が敵プレイヤーにダメージを与えることを通知するRPCを追加します。
C#
[Rpc(RpcSources.All, RpcTargets.StateAuthority)]
public void DealDamageRpc(float damage)
{
// The code inside here will run on the client which owns this object (has state and input authority).
Debug.Log("Received DealDamageRpc on StateAuthority, modifying Networked variable");
NetworkedHealth -= damage;
}
RpcSources.All
によって、誰でもRPCを呼び出せます。デフォルトでは、RPCを呼び出せるのは入力権限を持つクライアント(共有モードでは、状態権限を持つクライアントと同等)のみです。
RpcTargets.StateAuthority
を指定して、状態権限を持つクライアントのみでこのRPCを受信します。これにより、状態権限を持つクライアントが、ネットワークプロパティのHealth
を更新できるようになります。RPCメソッド内のコードはRpcTarget
に指定されたクライアント上で実行されるので、このケースでは、状態権限を持つ(ネットワークプロパティを更新できる)クライアントで実行されることになります。
さらに新規スクリプトを作成して、名前をRaycastAttack
にし、以下のコードを追加してください。
C#
using Fusion;
using UnityEngine;
public class RaycastAttack : NetworkBehaviour
{
public float Damage = 10;
public PlayerMovement PlayerMovement;
void Update()
{
if (HasStateAuthority == false)
{
return;
}
Ray ray = PlayerMovement.Camera.ScreenPointToRay(Input.mousePosition);
ray.origin += PlayerMovement.Camera.transform.forward;
if (Input.GetKeyDown(KeyCode.Mouse1))
{
Debug.DrawRay(ray.origin, ray.direction, Color.red, 1f);
}
}
}
このコードは、シングルプレイゲームのレイキャストの実装とほぼ同じです。射撃ボタンを押したプレイヤーのキャラクターだけでレイキャストを飛ばすようにするため、HasStateAuthority
で判定を行い、状態権限を持つクライアントのみで実行されるようにしています。
ターゲットにダメージを与えるためは、あとはRPCを呼び出すだけです。Debug.DrawRay
の行の下に、以下のコードを追加します。
C#
if (Physics.Raycast(ray.origin,ray.direction, out var hit))
{
if (hit.transform.TryGetComponent<Health>(out var health))
{
health.DealDamageRpc(Damage);
}
}
最後に、プレイヤーのプレハブにHealth
とRaycastAttack
コンポーネントを追加して、ビルドを作成しましょう。
その他のユースケース
RPCの最も一般的なユースケースは、状態権限を持つクライアントにネットワークプロパティを変更するように依頼することです。
その他、RPCが有効なユースケースは以下の通りです。
- 自由入力メッセージやエモート、その他のゲームプレイに影響しないプレイヤー間のインタラクション
- ゲームの起動(ゲームモードやマップの投票、または各プレイヤーの準備完了の通知)
ただ大抵のケースでは、プレイヤー間で状態を同期して変更検出ができれば十分です。
ゲームの実行
お疲れ様でした!共有モード入門のチュートリアルは全て完了です。全ての機能が正常に動作しているかを確認するため、ゲームを実行してテストしましょう。
ビルドを実行(Unityエディター上でゲームを実行)して、Start Shared Client
を押してください。他のプレイヤーを右クリックすると、コンソールにヘルス減少のメッセージが表示されます。
ヒエラルキー上のオブジェクトのネットワークプロパティHealth
の値は、Unityのインスペクターでも確認できます。