Version: 2020.3
言語: 日本語
プレイヤーゲームオブジェクト
ゲームオブジェクトのスポーン (spawn)

カスタムのプレイヤースポーン (Spawning)

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

Network Manager にはビルトインの基本的なプレイヤーのスポーン機能が備わっています。ただし、例えば、新しく生成するプレイヤーに色を指定するなど、プレイヤーのスポーンの処理にカスタマイズが必要な場合があります。

これを行うには、Network Manager のデフォルトの挙動を独自のスクリプトでオーバーライドする必要があります。

Network Manager がプレイヤー を追加する場合、プレイヤープレハブからゲームオブジェクトをインスタンス化し、それを接続に関連付けます。これを行うために、Network Manager は NetworkServer.AddPlayerForConnection を呼び出します。この動作を変更するには、NetworkManager.OnServerAddPlayer をオーバーライドします。OnServerAddPlayer のデフォルトの実装によって、プレイヤープレハブから新しいプレイヤーインスタンスをインスタンス化し、NetworkServer.AddPlayerForConnection を呼び出し、新しいプレイヤーインスタンスを生成します。さらに、カスタムの OnServerAddPlayer の実装では、NetworkServer.AddPlayerForConnection を呼び出す必要があります。ただし、このメソッド内で、必要とする他の初期化を自由に行うことができます。

以下の例では、プレイヤーの色をカスタマイズします。 まず、プレイヤープレハブに色のスクリプトを加えます。

using UnityEngine;
using UnityEngine.Networking;
class Player : NetworkBehaviour
{
    [SyncVar]
    public Color color;
}

次に、NetworkManager を作成してスポーンを処理します。

using UnityEngine;
using UnityEngine.Networking;
public class MyNetworkManager : NetworkManager
{
    public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId)
    {
        GameObject player = (GameObject)Instantiate(playerPrefab, Vector3.zero, Quaternion.identity);
        player.GetComponent<Player>().color = Color.red;
        NetworkServer.AddPlayerForConnection(conn, player, playerControllerId);
    }
}

NetworkServer.AddPlayerForConnection 関数は OnServerAddPlayer 内から呼び出される必要はありません。正しい接続のオブジェクトと playerControllerId が渡されている限り、OnServerAddPlayer が返された後に呼び出されます。これにより、リモートデータソースからプレイヤーデータをロードするなど、非同期ステップの発生を可能にします。

ほとんどのマルチプレイヤーゲームでは、通常、クライアントごとに 1 プレイヤーが必要ですが、HLAPI はプレイヤーとクライアントを別々の概念として扱います。なぜなら、ある場合では (例えば、複数のコントローラーが 1 つのコンソールシステムに接続している場合)、1 つの接続で複数のプレイヤーゲームオブジェクトが必要な場合があるからです。1 つの接続に対して複数のプレイヤーが存在する場合、 playerControllerId プロパティを使ってそれぞれを区別します。この識別子は接続に関連していて、プレイヤーに関連するコントローラーの ID をクライアントにマッピングします。

システムは、自動的にプレイヤーゲームオブジェクトを生成し、サーバー上の NetworkServer.AddPlayerForConnection に渡します。そのため、NetworkServer.Spawn をプレイヤーのために呼び出す必要はありません。プレイヤーの準備が整ったら、シーン内のアクティブなネットワーク化されたゲームオブジェクト (関連した NetworkIdentity を持つゲームオブジェクト) が、プレイヤーのクライアントで生成されます。ゲーム内のネットワーク化されたゲームオブジェクトはすべてクライアントの最新の状態で作成されます。そのため、ゲーム内の他の参加者と同期が可能になります。

プレイヤーゲームオブジェクトを作成するために NetworkManagerplayerPrefab を使う必要はありません。さまざまなプレイヤーを作成するために異なるメソッドの使用が可能です。

準備完了の状態

プレイヤーに加え、クライアントの接続にも “準備完了” の状態が存在します。ホストは準備が完了したクライアントに、生成されたオブジェクトと状態同期の更新に関する情報を送信します。一方で、準備の整っていないクライアントにはこれらの情報は送信されません。クライアントがサーバーに初めて接続するとき、この準備は整っていません。準備が整っていない間、クライアントはサーバー上でゲームの状態によるリアルタイムインタラクションを必要としないこと (例えば、シーンのロード、アバターの選択や、ログインの入力するなど) を実行できます。クライアントがすべてのゲーム実行前の作業を終え、アセットをすべてロードしたら、“準備完了” 状態にするために ClientScene.Ready を呼び出します。上の基本的な例は、“準備完了” 状態の実装を表しています。まだクライアントが準備完了状態になっていない場合は、NetworkServer.AddPlayerForConnection を用いてプレイヤーを加えることでも、クライアントを準備完了の状態にします。

クライアントは準備完了していなくてもネットワークメッセージを送信、受信することができます。つまり、アクティブなプレイヤーゲームオブジェクト無しに、そうすることが可能だということを意味しています。そのため、クライアントはメニューや選択スクリーンで、プレイヤーオブジェクトが存在しないにも関わらずゲームへと接続し、相互作用することができます。コマンドや RPC 呼び出しを使用しないメッセージの送信に関する詳細は、ネットワークメッセージ を参照してください。

プレイヤーの切り替え

接続に使用するプレイヤーオブジェクトを取り換えるには NetworkServer.ReplacePlayerForConnection を使用します。この機能は、ゲーム前のロビー画面など、プレイヤーが特定の期間発行できるコマンドを制限するのに便利です。この関数は AddPlayerForConnection と同じ引数を取りますが、すでに接続しているプレイヤーへも使用することができます。変更前のプレイヤーオブジェクトを破棄する必要はありません。ロビー内すべてのプレイヤーの準備が完了している場合、NetworkLobbyManager は、この方法を用いて NetworkLobbyPlayer ゲームオブジェクトからゲームプレイヤーゲームオブジェクトに切り替えます。

また、ゲームオブジェクトを破棄した後に、ReplacePlayerForConnection を使用してプレイヤーを再生成することができます。場合によっては、単にゲームオブジェクトを無効にして、そのゲーム属性を再生成にするほうが良い場合があります。以下のコードサンプルは、実際に、破棄したゲームオブジェクトを新しいゲームオブジェクトで置き換える方法を示しています。

class GameManager
{
    public void PlayerWasKilled(Player player)
    {
        var conn = player.connectionToClient;
        var newPlayer = Instantiate<GameObject>(playerPrefab);
        Destroy(player.gameObject);
        NetworkServer.ReplacePlayerForConnection(conn, newPlayer, 0);
    }
}

プレイヤーゲームオブジェクトの接続が断たれると、クライアントはコマンドを実行できなくなります。ただし、ネットワークメッセージは送信することができます。

ReplacePlayerForConnection を使用するには、ゲームオブジェクトとクライアント間の関係を作るために、プレイヤーのクライアントの NetworkConnection ゲームオブジェクトが必要です。これは、通常は、NetworkBehaviour クラスの connectionToClient プロパティーですが、古いプレイヤーがすでに破棄されている場合は、使用可能になっていない場合があります。

接続を探すために、いくつか使用可能なリストがあります。NetworkLobbyManager を使用している場合、ロビープレイヤーは lobbySlots で見つけることができます。また、NetworkServer には connectionslocalConnections のリストがあります。

プレイヤーゲームオブジェクト
ゲームオブジェクトのスポーン (spawn)