生成と再生成

確認済のバージョン: 5.3

-

難易度: 中級

プレイヤーの初期生成位置を設定する

この段階ではプレイヤーは、元々の位置または Vector3.zero の位置に生成(Spawn)および再生成(Respawn)されます。ゲームの開始時には、プレイヤーのどれかを動かした後に別のプレイヤーが参加するということのない限り、全てのプレイヤーが同じ位置に存在する状態になります。しかし、プレイヤーはそれぞれ異なる位置に生成されるようにするのが理想的です。これは、生成位置をハンドルする機能がビルトインされた NetworkStartPosition コンポーネントを使用して行うことができます。

2 つの異なる生成位置を作成するには、それぞれに NetworkStartPosition コンポーネントの添付された新規ゲームオブジェクトを 2 つ作成する必要があります。

  • 空のゲームオブジェクトを 1 つ新規作成してください。
  • 新規作成したゲームオブジェクトの名前を “Spawn Position 1” に変更してください。
  • Spawn Position 1 ゲームオブジェクトが選択された状態で、
  • ... Network > NetworkStartPosition コンポーネントを追加してください。
  • ... Transform Position を (3, 0, 0) に設定してください。
  • Spawn Position 1 ゲームオブジェクトの複製を作成してください。
  • 複製したゲームオブジェクトの名前を “Spawn Position 2” に変更してください。
  • Spawn Position 2 ゲームオブジェクトが選択された状態で、
  • ... Transform Position を (-3, 0, 0) に設定してください。
  • Hierarchy ウィンドウで Network Manager ゲームオブジェクトを選択してください。
  • Network Manager ゲームオブジェクトが選択された状態で、
  • ... Spawn Info のドロップダウンメニューを開いてください。
  • ... Player Spawn MethodRound Robin に変更してください。

Spawn Position ゲームオブジェクトは NetworkStartPosition コンポーネントを持っているので、NetworkManager によって自動的に検知されます。

NetworkManager は、クライアントがサーバーに接続されると、そのクライアントのゲームオブジェクトに添付された NetworkStartPositionTransform Position によって設定される位置に、新しいプレイヤーゲームオブジェクトを生成します。

Player Spawn Methods(プレイヤーの生成方法)は、RandomRound Robin の二種類存在します。

Random は、使用可能な NetworkSpawnPosition の位置の中からランダムに選んだ位置を使用するのに対し、Round Robin は、(同じ位置をランダムに繰り返し使うことなく、)使用可能な全ての生成位置を順番に(周期的に)使用します。

Random の場合、複数のプレイヤーゲームオブジェクトに同じ生成位置が使用されることも十分にあり得ます。これは、接続されたクライアントの数にもよります。Round Robin の場合、生成位置の数よりクライアントの数が多い場合以外は、生成位置が重複して使用されることはありません。

加えた変更をテストします。

  • このシーンを、スタンドアロンのアプリケーションとして Build and Run(ビルドおよび実行)します。
  • ゲーム内 UI から Host ボタンをクリックすると、このゲームがホストとして開始されます。
  • Unity に戻ってください。
  • Play モードを開始します。
  • ゲーム内 UI から LAN Client ボタンをクリックすると、クライアントとしてホストに接続されます。

ゲームが開始されると、シーン内の異なる場所にプレイヤーが生成されるはずです。

  • スタンドアロン プレイヤーを終了してください。
  • Unity に戻ってください。
  • Play モードを終了してください。

Respawn(再生成)位置を設定する

サンプルプロジェクトの最後のステップとして、Spawn Position ゲームオブジェクトに NetworkStartPosition コンポーネントを使用した、簡単な仕組みを作成します。これにより生成位置の配列を作成し、プレイヤーの再生成時の位置をその中から選ぶことができるようにします。このステップは、マルチプレイヤーネットワーキングのサンプルプロジェクトにとって必ずしも不可欠ではありませんが、より完成度の高い印象にするためのものです。

再生成位置の保存方法として、更にシンプルなものもあります。Start 関数内のローカルプレイヤーの位置を再生成位置として確保する方法です。この方法では、Network ManagerRound Robin Player Spawn Method により選択される生成位置は、該当プレイヤーによって「占拠される」ことになります。

再生成の仕組みを作成するには、配列を作成し、NetworkStartPosition の添付された全てのゲームオブジェクトを検索して配列に追加し、そのオブジェクトの Transform Position を再生成位置として使用するようにします。これは、Network Manager によって自動的に行われる開始位置の処理に非常に類似していますが、ここではより単純に、Round Robin ではなく Random を使用します。

  • 編集用に Health スクリプトを開いてください。
  • 生成位置を含めるための、NetworkStartPosition タイプの新しい配列を追加してください。
private NetworkStartPosition[] spawnPoints;

  • Start 関数を追加してください。
void Start ()
{

}

  • Start 関数内に、このゲームオブジェクトが該当の Local Player と関連付けられているかどうかをテストするチェックを追加してください。
if (isLocalPlayer)
{
            
}

  • NetworkStartPosition コンポーネントの全てのインスタンスを検索してそれを Spawn Points 配列に保存するロジックを追加してください。
spawnPoints = FindObjectsOfType<NetworkStartPosition>();

これは「FindObjectsOfType」と、複数バージョンであることにご注目ください。

  • RpcRespawn 関数内の isLocalPlayer チェック内にある既存のコードを削除してください
// プレイヤーの位置を、元々の位置に設定する
transform.position = Vector3.zero;

  • RpcRespawn 関数内の、isLocalPlayer チェック内のコードを、生成位置(spawn points)の配列から抽出したランダムな位置を使用するように更新してください。
// 初期値として生成位置を元々の位置に設定する
Vector3 spawnPoint = Vector3.zero;

// 生成位置の配列があって、それが空でなければ、ランダムに生成位置を抽出する
if (spawnPoints != null && spawnPoints.Length > 0)
{
    spawnPoint = spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position;
}

// プレイヤーの位置を、選択された生成位置に設定する
transform.position = spawnPoint;

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

Health (体力)

Code snippet

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;

public class Health : NetworkBehaviour {

    public const int maxHealth = 100;
    public bool destroyOnDeath;

    [SyncVar(hook = "OnChangeHealth")]
    public int currentHealth = maxHealth;

    public RectTransform healthBar;

    private NetworkStartPosition[] spawnPoints;

    void Start ()
    {
        if (isLocalPlayer)
        {
            spawnPoints = FindObjectsOfType<NetworkStartPosition>();
        }
    }

    public void TakeDamage(int amount)
    {
        if (!isServer)
            return;
        
        currentHealth -= amount;
        if (currentHealth <= 0)
        {
            if (destroyOnDeath)
            {
                Destroy(gameObject);
            } 
            else
            {
                currentHealth = maxHealth;

                // サーバーで呼び出され、クライアントで実行される
                RpcRespawn();
            }
        }
    }

    void OnChangeHealth (int currentHealth )
    {
        healthBar.sizeDelta = new Vector2(currentHealth , healthBar.sizeDelta.y);
    }

    [ClientRpc]
    void RpcRespawn()
    {
        if (isLocalPlayer)
        {
            // 初期値として生成位置を元々の位置に設定する
            Vector3 spawnPoint = Vector3.zero;

            // 生成位置の配列があって、それが空でない場合は、ランダムに 1 つ抽出する
            if (spawnPoints != null && spawnPoints.Length > 0)
            {
                spawnPoint = spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position;
            }

            // プレイヤーの Position を、選択された生成位置に設定する
            transform.position = spawnPoint;
        }
    }
}
  • スクリプトを保存します。
  • Unity に戻ってください。

加えた変更をテストします。

  • このシーンを、スタンドアロンのアプリケーションとして Build and Run(ビルドおよび実行)します。
  • ゲーム内 UI から Host ボタンをクリックすると、このゲームがホストとして開始されます。
  • Unity に戻ってください。
  • Play モードを開始します。
  • ゲーム内 UI から LAN Client ボタンをクリックすると、クライアントとしてホストに接続されます。

これで、ゲームの開始時に、シーン内の異なる位置にプレイヤーが生成されるようになりました。プレイヤーの「現在の体力」がゼロになると、そのプレイヤーは既存の再生成位置のどれかからランダムに再生成されます。

  • スタンドアロン プレイヤーを終了してください。
  • Unity に戻ってください。
  • Play モードを終了してください。