Version: 2020.3
言語: 日本語
Multiplayer クラスリファレンス
NetworkClient

NetworkBehaviour

重要: UNet は非推奨のソリューションであり、新しい Multiplayer and Networking Solution (MLAPI) が開発途中です。詳細については、Unity MLAPI ウェブサイトの情報 を参照してください。

Unity のネットワークのサーバーが権限を持つシステムでは、サーバーは NetworkServer.Spawn 関数を使用して、Network Identity コンポーネントを持つゲームオブジェクトをスポーンする必要があります。このようにすることにより、ゲームオブジェクトに NetworkInstanceId を割り当て、サーバーに接続するクライアント上にゲームオブジェクトを作成します。

注意: NetworkBehaviour はゲームオブジェクトに直接加えることのできるコンポーネントではありません。そうではなく、NetworkBehaviour (デフォルトの MonoBehaviour の代わりに) を継承するスクリプトを作成する必要があります。次に、このスクリプトをコンポーネントとしてゲームオブジェクトに加えます。

プロパティ

プロパティ 説明
isLocalPlayer ゲームオブジェクトがローカルクライアントのプレイヤーである場合は True を返します。
isServer ゲームオブジェクトがサーバー上で動作し、スポーンされている場合は True を返します。
isClient ゲームオブジェクトがクライアント上にあり、サーバーによってスポーンされている場合は True を返します。
hasAuthority このオブジェクトが権限を持つゲームオブジェクト (つまり、同期するときに、変更の元となるオブジェクト) である場合、True を返します。サーバー上では、大抵のゲームオブジェクトが True を返します。ただし、NetworkIdentity の localPlayerAuthority が True の場合、権限はプレイヤーのクライアントにあり、この値はサーバー上ではなく、クライアント上で True になります。
netId ゲームオブジェクトの独自のネットワーク ID で、ランタイムにサーバーによって割り当てられます。 ネットワークセッション内ですべてのゲームオブジェクトに与えられる一意の ID です。
playerControllerId NetworkBehaviour スクリプトに関連づけられたプレイヤーの ID です。
connectionToServer Network Identity コンポーネントに関連付けられた NetworkConnection で、ゲームオブジェクトに設定されます。これは、クライアント上のプレイヤーオブジェクトのみに有効です。
connectionToClient Network Identity コンポーネントに関連付けられた NetworkConnection で、ゲームオブジェクトに設定されます。これは、サーバー上のプレイヤーゲームオブジェクトのみに有効です。
localPlayerAuthority この値は Network Identity コンポーネント上で設定され、利便性のため、スクリプトを使用する場合は NetworkBehaviour スクリプトを使ってアクセス可能です。

NetworkBehaviour スクリプトは以下の機能を持っています。

  • 変数の同期

  • ネットワークコールバック

  • サーバー関数とクライアント関数

  • コマンドの送信 (Command)

  • クライアントの RPC 呼出し (ClientRPC)

  • ネットワーク化されたイベント

変数の同期

NetworkBehaviour スクリプトのメンバー変数をサーバーからクライアントに対し同期できます。このシステムではサーバーに権限があるため、同期はサーバーからクライアントへの方向でのみ行われます。

SyncVar 属性を使用して、メンバー変数に同期済みのタグを付けます。同期される変数には、任意の基本型 (bool、byte、sbyte、char、decimal、double、 Float、int、uint、long、ulong、short、ushort、string) を使用できますが、クラス、リスト、その他のコレクションは使用できません。

public class SpaceShip : NetworkBehaviour
{
    [SyncVar]
    public int health;

    [SyncVar]
    public string playerName;
}

サーバー上で SyncVar の値が変更される場合、サーバーはゲーム内の準備完了したすべてのクライアントに新しい値を自動的に送信し、それらのクライアント上の対応する SyncVar 値を更新します。ゲームオブジェクトがスポーンされる場合、ゲームオブジェクトはサーバーから送信されるすべての SyncVar 属性が最新の状態でクライアント上に作成されます。

注意: クライアントからサーバーに要求を行うには、同期された変数ではなく コマンド を使用する必要があります。詳細は、コマンドの送信に関するドキュメントを参照してください。

ネットワークコールバック

さまざまなネットワークイベントを NetworkBehaviour 上で実行するビルトインのコールバック関数があります。これらは基本クラスの仮想関数であるため、以下のようにオーバーライドして独自のコードに使用することができます。

public class SpaceShip : NetworkBehaviour
{
    public override void OnStartServer()
    {
        // クライアントのものを無効にします
    }

    public override void OnStartClient()
    {
        // クライアントイベントを設定。効果を有効にします
    }
}

ビルトインのコールバック は以下の通りです。

  • OnStartServer - ゲームオブジェクトがサーバー上で生成されるとき、またはシーンのゲームオブジェクトのためにサーバーが起動されたときに呼び出されます。

  • OnStartClient - ゲームオブジェクトがクライアント上で生成されるとき、または、クライアントがシーンのゲームオブジェクトのためにサーバーに接続するときに呼び出されます。

  • OnSerialize - 状態を取得してサーバーからクライアントに送信するために呼び出されます。

  • OnDeSerialize - クライアント上のゲームオブジェクトに状態を適用するために呼び出されます。

  • OnNetworkDestroy - サーバーがゲームオブジェクトを除去するときにクライアント上で呼び出されます。

  • OnStartLocalPlayer - ローカルクライアント上のプレイヤーゲームオブジェクトのため (のみ) にクライアント上で呼び出されます。

  • OnRebuildObservers - ゲームオブジェクトのオブザーバーのセットが再構築されるときにサーバー上で呼び出されます。

  • OnSetLocalVisibility - ゲームオブジェクトの可視性がローカルクライアントに対して変更されるときに、クライアントやサーバー上で呼び出されます。

  • OnCheckObserver - 新しいクライアントの可視性の状態を確認するためにサーバーで呼び出されます。

ピアホストの設定では、クライアントの 1 つがホストとクライアントの両方として動作している場合に、同じゲームオブジェクト上で OnStartServerOnStartClient の両方が呼び出されることに注意してください。これらの関数は、サーバーへの影響を抑制したり、クライアント側のイベントを設定するなど、クライアントかサーバーいずれかに特有の処理に役立ちます。

サーバー関数とクライアント関数

NetworkBehaviour スクリプトのメンバー関数をカスタムの属性でタグ付けし、サーバーのみ、または、クライアントのみと指定することができます。

using UnityEngine;
using UnityEngine.Networking;

public class SimpleSpaceShip : NetworkBehaviour
{
    int health;

    [Server]
    public void TakeDamage( int amount)
    {
        // サーバーでのみ作動します
        health -= amount;
    }

    [ServerCallback]
    void Update()
    {
        // コールバックを発します- サーバーでのみ実行されます
    }


    [Client]
    void ShowExplosion()
    {
        // クライアントでのみ実行します
    }

    [ClientCallback]
    void Update()
    {
        // コールバックを発します- クライアントでのみ実行されます
    }
}

[Server][ServerCallback]はクライアントがアクティブでないときには、即座に実行されます。同様に、[Client][ClientCallback] はサーバーがアクティブでないときには、即座に実行されます。

[Server][Client] 属性は、独自のカスタムコールバック関数用です。それらはコンパイルタイムエラーを出しませんが、誤ったスコープで呼び出されると警告のログメッセージを出力します。

[ServerCallback][ClientCallback] 属性は、ビルトインのコールバック関数用です。それらは Unity によって自動的に呼び出されます。これらの属性が原因で警告が発生することはありません。

詳細は、以下の属性に関するスクリプトリファレンスを参照してください。

コマンドの送信

サーバー上でコードを実行するには、コマンド を使用します。高レベル API はサーバー権限のシステムのため、コマンドはクライアントがサーバー上のコードを起動する唯一の方法です。

プレイヤーゲームオブジェクトのみが、コマンドを送信できます。

クライアントのプレイヤーゲームオブジェクトがコマンドを送信する場合、コマンドはサーバー上の対応するプレイヤーゲームオブジェクト上で実行されます。このルーティングは自動的に発生するため、クライアントが違うプレイヤーにコマンドを送信するのは不可能です。

コード内で コマンド を定義するには、以下を含む関数を作成する必要があります。

  • Cmd で始まる名前

  • [Command] 属性

例:

using UnityEngine;
using UnityEngine.Networking;

public class SpaceShip : NetworkBehaviour
{
    bool alive;
    float thrusting;
    int spin;

    [ClientCallback]
    void Update()
    {

        // このコードはクライアント上で実行され、入力を収集します
        int spin = 0;
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            spin += 1;
        }
        if (Input.GetKey(KeyCode.RightArrow))
        {
            spin -= 1;
        }


        // サーバーで実行されるコードを起動します
        CmdThrust(Input.GetAxis("Vertical"), spin);
    }

    [Command]
    public void CmdThrust(float thrusting, int spin)
    {   

        // このコードが Update() の後に呼び出された後に

        // コードが実行されます
        if (!alive)
        {
            this.thrusting = 0;
            this.spin = 0;
            return;
        }
            
        this.thrusting = thrusting;
        this.spin = spin;
    }

}

コマンドは、単に通常通りにクライアント上の関数を呼び出すだけで呼び出されます。クライアント上でコマンド関数を実行する代わりに、サーバ上にある対応するプレイヤーゲームオブジェクトで自動的にコマンド関数が呼び出されます。

つまり、コマンドはタイプセーフで、ビルトインのセキュリティーとプレイヤーへのルーティング機能を持ち、引数の効率的なシリアライゼーションを使用して高速で呼び出すことができます。

クライアントの RPC 呼び出し

クライアントの RPC 呼び出しは、サーバーのゲームオブジェクトがクライアントのゲームオブジェクトに何かを発生させるための方法です。

クライアントの RPC 呼び出しは、プレイヤーゲームオブジェクトに制限されているわけではありません。Network Identity コンポーネントを持つすべてのゲームオブジェクトで呼び出すことが可能です。

コード内で クライアントの RPC 呼び出し を定義するには、以下のような関数を作成する必要があります。

  • Rpc で始まる名前を持っていること

  • [ClientRPC] 属性をもっていること

例:

using UnityEngine;
using UnityEngine.Networking;

public class SpaceShipRpc : NetworkBehaviour
{
    [ServerCallback]
    void Update()
    {

        // サーバー上で実行するコードです
        int value = UnityEngine.Random.Range(0,100);
        if (value < 10)
        {
            // すべてのクライアント上で RpcDoOnClient 関数を発生させます
            RpcDoOnClient(value);
        }
    }

    [ClientRpc]
    public void RpcDoOnClient(int foo)
    {

        // すべてのクライアント上で実行されます
        Debug.Log("OnClient " + foo);
    }

}

ネットワーク化されたイベント

ネットワーク化されたイベントクライアントの RPC 呼び出しのようなものです。ただし、ゲームオブジェクト上の関数を呼び出す代わりに、イベントを発生させます。

ネットワーク化されたイベントを使って、イベントが発生するときのコールバックを設定するスクリプトを作成できます。

コード内で ネットワーク化されたイベント を定義するには、以下のような関数を作成する必要があります。

  • Event で始まる名前を持っていること

  • [SyncEvent] 属性をもっていること

イベントを使用して、他のスクリプトで拡張可能な強力なネットワーク化されたゲームシステムを構築できます。この例は、クライアントの効果のスクリプトがサーバーの Combat スクリプトによって生成されたイベントにどのように応答するかを示しています。

SyncEvent は、CommandsClientRPC 呼出しが派生する基本クラスです。独自に作成した関数で SyncEvent 属性を使用して、独自のイベントを利用するネットワーク化したゲームコードを作成できます。SyncEvent を使用して、Unity の Multiplayer 機能を拡張し、自身のプログラムのスタイルに合わせることができます。以下はその例です。

using UnityEngine;
using UnityEngine.Networking;

// サーバースクリプト
public class MyCombat : NetworkBehaviour
{
    public delegate void TakeDamageDelegate(int amount);
    public delegate void DieDelegate();
    public delegate void RespawnDelegate();
    
    float deathTimer;
    bool alive;
    int health;

    [SyncEvent(channel=1)]
    public event TakeDamageDelegate EventTakeDamage;
    
    [SyncEvent]
    public event DieDelegate EventDie;
    
    [SyncEvent]
    public event RespawnDelegate EventRespawn;

    [ServerCallback]
    void Update()
    {

        // 再スポーンすべきかを確認
        if (!alive)
        {
            if (Time.time > deathTimer)
            {
                Respawn();
            }
            return;
        }
    }

    [Server]
    void Respawn()
    {
        alive = true;


        // サーバーからすべてのクライアントに再スポーンイベントを送信
        EventRespawn();
    }


    [Server]
    void EventTakeDamage(int amount)
    {
        if (!alive)
            return;
            
        if (health > amount) {
            health -= amount;
        }
        else
        {
            health = 0;
            alive = false;


            // すべてのクライアントに Die イベントを送信
            EventDie();
            deathTimer = Time.time + 5.0f;
        }
    }
}
Multiplayer クラスリファレンス
NetworkClient