This document is about: FUSION 2
SWITCH TO

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 (Runner.GetPhysicsScene().Raycast(ray.origin,ray.direction, out var hit))
{
    if (hit.transform.TryGetComponent<Health>(out var health))
    {
        health.DealDamageRpc(Damage);
    }
}

最後に、プレイヤーのプレハブにHealthRaycastAttackコンポーネントを追加して、ビルドを作成しましょう。

その他のユースケース

RPCの最も一般的なユースケースは、状態権限を持つクライアントにネットワークプロパティを変更するように依頼することです。

その他、RPCが有効なユースケースは以下の通りです。

  1. 自由入力メッセージやエモート、その他のゲームプレイに影響しないプレイヤー間のインタラクション
  2. ゲームの起動(ゲームモードやマップの投票、または各プレイヤーの準備完了の通知)

ただ大抵のケースでは、プレイヤー間で状態を同期して変更検出ができれば十分です。

ゲームの実行

お疲れ様でした!共有モード入門のチュートリアルは全て完了です。全ての機能が正常に動作しているかを確認するため、ゲームを実行してテストしましょう。

ビルドを実行(Unityエディター上でゲームを実行)して、Start Shared Clientを押してください。他のプレイヤーを右クリックすると、コンソールにヘルス減少のメッセージが表示されます。

ヒエラルキー上のオブジェクトのネットワークプロパティHealthの値は、Unityのインスペクターでも確認できます。

次は 共有モード入門 6 - 次のステップ

Back to top