プレイヤーの動きをネットワーク化する

確認済のバージョン: 5.3

-

難易度: 中級

プレイヤーの動きをネットワークと連携させ、ローカルプレイヤーのみがローカルプレイヤーゲームオブジェクトを制御できるようにするには、PlayerController スクリプトを更新する必要があります。

PlayerController スクリプトへの最も大きな変更は、名前空間 UnityEngine.Networking を使用することと、MonoBehaviour ではなく NetworkBehaviour から PlayerController スクリプトを派生させることです。

  • 編集用に PlayerController スクリプトを開きます。
  • 名前空間 UnityEngine.Networking を追加してください。
using UnityEngine.Networking;

  • MonoBehaviourNetworkBehaviour に変更してください。
public class PlayerController : NetworkBehaviour

  • Update 関数内の isLocalPlayer にチェックを追加し、入力がローカルプレイヤーのみによって処理されるようにします。
if (!isLocalPlayer)
{
    return;
}

最終的なスクリプトは以下のようになります。

PlayerController

Code snippet

using UnityEngine;
using UnityEngine.Networking;

public class PlayerController : NetworkBehaviour
{
    void Update()
    {
        if (!isLocalPlayer)
        {
            return;
        }

        var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
        var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;

        transform.Rotate(0, x, 0);
        transform.Translate(0, 0, z);
    }
}

名前空間 UnityEngine.Networking に、ネットワークを認識するスクリプトを書くために必要なネットワーキングコードが含まれています。名前空間についての詳細は、Unity マニュアルの名前空間に関するページ をご覧ください。

NetworkBehaviour クラスは、Monobehaviour に基づく特殊なクラスです。ネットワーキング機能を使用する必要のあるゲームオブジェクトに添付されたスクリプトは、NetworkBehaviour から継承する必要があります。詳細は NetworkBehaviour に関する スクリプトリファレンス または マニュアル のページをご覧ください。

!isLocalPlayer を使用しているチェックにご注目ください。LocalPlayerNetworkBehaviour の一部であり、NetworkBehaviour から派生する全てのスクリプトは LocalPlayer の概念を理解します。

LocalPlayer とは何か、またそれがどのように機能するかを理解するには、高レベル API (Multiplayer Networking High Level API)HLAPI)を使用したプロジェクトについての理解が必要です。HLAPI に関する詳細は、HLAPI に関するページ でご確認ください。

ネットワーク化されたプロジェクトでは、サーバーとクライアントの全てが、同じスクリプトの同じコードを、同じゲームオブジェクトについて同時に実行しています。したがってサーバーが 1 つにクライアントが 2 つある場合、最大で 6 体のプレイヤーゲームオブジェクトが処理されることになります。つまり、プレイヤーが 2 人いるのでサーバー上に 2 体のプレイヤーゲームオブジェクトが存在し、また 2 つのクライアントのそれぞれにもプレイヤーが 2 体存在することになるので、合計のプレイヤーゲームオブジェクトの数は 6 になるというわけです。

参考画像

これらのプレイヤーゲームオブジェクトは全て同一のプレイヤープレハブアセットから生成されたものであり、同一の PlayerController スクリプトのコピーを共有しています。NetworkBehaviour から派生するスクリプトがあることで、どのプレイヤーがどのゲームオブジェクトを「所有」しているかが自動的に検知され、生成プロセスの一環として処理されます。LocalPlayer は、ローカルクライアントが「所有」するプレイヤーゲームオブジェクトです。この所有関係は、クライアントがサーバーに接続されて新しいプレイヤーゲームオブジェクトがプレイヤープレハブから作成された際に、ネットワークマネージャーによって設定されます。あるクライアントがサーバーに接続されると、そのローカルクライアント上で作成されたインスタンスは LocalPlayer として登録されます。このプレイヤーを表すその他全ての(サーバー上または別のクライアント上にある)プレイヤーゲームオブジェクトは、LocalPlayer としては登録されません。

ブール型チェック isLocalPlayer を使用すると、コードが LocalPlayer によって所有されている かいないかによって、スクリプトがそのコードを認識または無視するようにすることができます。この参考例では、Update 内に以下のようなチェックが存在します。

if (!isLocalPlayer)
{
    return;
}

このチェックのおかげで、動きのコードは LocalPlayer だけが実行できるようになっています。このサンプルプロジェクトのようにサーバーが 1 つ、クライアントが 2 つの場合、サーバーおよびリモートクライアント上のプレイヤーゲームオブジェクトは LocalPlayer にはなりません。この場合、コードパスが 戻され、動きのコードは実行されません。このおかげで、サーバーで処理されているかクライアント上で処理されているかに関わらず、全てのゲームオブジェクト上で同一のスクリプトが正常に機能するようになっています。

仮にこの時点でサンプルプロジェクトを実行した場合、プロジェクトの全てのインスタンス間でプレイヤーゲームオブジェクトの同期が維持された状態にはなりません。動きの入力処理はローカルのプレイヤーゲームオブジェクトに関してのみ行われ、そのプレイヤーゲームオブジェクトの位置や角度がネットワークを介して更新されることはありません。

プレイヤーゲームオブジェクトの同期を維持するためには、プレイヤープレハブに NetworkTransform コンポーネントを追加する必要があります。

  • スクリプトを保存してください。
  • Unity に戻ってください。
  • Project ウィンドウでプレイヤープレハブ アセットを選択してください。
  • プレイヤープレハブ アセットが選択された状態で、
  • ... Network > NetworkTransform コンポーネントを追加してください。
  • プロジェクトを保存してください。

参考画像

この NetworkTransform がゲームオブジェクトの Transform をネットワークを介して同期します。ローカルプレイヤーはローカルで所有されたプレイヤーゲームオブジェクトのみを動かします。これは、isLocalPlayer のチェックがあるためです。このプレイヤーゲームオブジェクトの NetworkTransform は、そのゲームオブジェクトの Transform の位置(Position)・角度(Rotation)・縮尺(Scale)を、サーバーおよび全てのクライアント上で同期します。NetworkTransform コンポーネントに関する詳細は NetworkTransform に関するページ をご覧ください。