PUN Classic(PUN1とも呼ばれます)はPUNのはじめの主要バージョンです。         現在は、リファクタリングおよび機能拡張されたPUN2に切り替わっています。         新しいプロジェクトはPUN2をご利用いただき、また可能であれば既存のプロジェクトについてもPUN1からPUN2へ移行していただくよう強く推奨しています。 こちらをご参照ください: "移行情報". PUN Cloassicは今後数か月メンテナンスされます。       重要なバグの修正や新しいUnityバージョンのサポートは行いますが、新機能の追加はPUN2のみとなります。

8-プレイヤーのインスタンス化

このセクションでは、ネットワーク上の「プレイヤー」プレハブのインスタンス化について説明します。プレイ中の自動シーン切り替えに必要となる様々な機能を実装します。

Contents

プレイヤーのインスタンス化

「プレイヤー」プレハブのインスタンス化は非常に簡単です。 ルームに入室した際にインスタンス化する必要があり、アリーナを読み込んだことを示すGameManager script's Start()メソッドに依存することができます。これは、私たちの設計ではルームに入ったことを意味します。

  1. GameManagerスクリプトを開きます。
  2. Variablesリージョンで以下の変数を追加します。

        [Tooltip("The prefab to use for representing the player")]
    public GameObject playerPrefab;
  3. Start()メソッドで、以下を追加してGameManagerスクリプトを保存します。

        if (playerPrefab == null)
    {
        Debug.LogError("<Color=Red><a>Missing</a></Color> playerPrefab Reference. Please set it up in GameObject 'Game Manager'",this);
    }
    else
    {
        Debug.Log("We are Instantiating LocalPlayer from "+Application.loadedLevelName);
    // we're in a room. spawn a character for the local player. it gets synced by using PhotonNetwork.Instantiate
        PhotonNetwork.Instantiate(this.playerPrefab.name, new Vector3(0f,5f,0f), Quaternion.identity, 0);
    }
  4. GameManagerスクリプトを保存します。

これにより「プレイヤー」プレハブを参照するパブリックフィールドが公開されます。 このパブリックフィールドではプレイヤープレハブはアセットで、また参照がそのまま保持されるため(プレハブが同じシーンでインスタンス化した場合のみ行うことができる、階層でのGameObjectの参照ではなく)、各シーンではなくGameManagerプレハブに直接ドラッグアンドドロップできて便利です。

警告:ネットワーク上でインスタンス化する必要のあるプレハブがResourcesフォルダに入っていることを確認してください。これはPhotonの要件です。

GameManager Inspector
GameManagerインスペクター

次にStart()でインスタンス化します (「Player」プレハブが参照されていることを正常に確認した後)

床よりだいぶ上の位置でインスタンス化していることに留意してください(プレイヤーは2ユニットの高さですが、インスタンスは5ユニットの高さです)。 これは、新しいプレイヤーがルームに参加する際の衝突を防ぐ方法のひとつです。プレイヤーがアリーナの中央付近で既に移動している可能性があるので、突然の衝突を避けることができます。 「落下中」のプレイヤーはゲームでの新しいエンティティを意味します。

今回の場合はそれでは不十分です。 他のプレイヤーが参加する場合、異なるシーンが読み込まれます。その際、1人のプレイヤーの退室によって既存のプレイヤーが破棄されることを防ぎ、一貫性を維持する必要があります。そのため、作成したインスタンスを破棄しないようUnityに伝える必要があります。つまり、シーンが読み込まれたときにインスタンス化が必要かどうかを確認する必要があります。

Back To Top

プレイヤーインスタンスをトラッキング

  1. PlayerManagerスクリプトを開きます。
  2. "Public Variables"リージョンに以下を追加します。

        [Tooltip("The local player instance. Use this to know if the local player is represented in the Scene")]
    public static GameObject LocalPlayerInstance;
  3. Awake()メソッドで、以下を追加します。

        // #Important
    // used in GameManager.cs: we keep track of the localPlayer instance to prevent instantiation when levels are synchronized
    if ( photonView.isMine)
    {
        PlayerManager.LocalPlayerInstance = this.gameObject;
    }
    // #Critical
    // we flag as don't destroy on load so that instance survives level synchronization, thus giving a seamless experience when levels load.
    DontDestroyOnLoad(this.gameObject);
  4. PlayerManagerスクリプトを保存します。

これらの変更により、GameManagerスクリプト内で必要な場合にのみインスタンス化するためのチェックを実装することができます。

  1. GameManager スクリプトを開きます。
  2. if文でインスタンス化コールを囲みます。

        if (PlayerManager.LocalPlayerInstance==null)
    {
        Debug.Log("We are Instantiating LocalPlayer from "+Application.loadedLevelName);
        // we're in a room. spawn a character for the local player. it gets synced by using PhotonNetwork.Instantiate
        PhotonNetwork.Instantiate(this.playerPrefab.name, new Vector3(0f,5f,0f), Quaternion.identity, 0);
    }
    else
    {
        Debug.Log("Ignoring scene load for "+Application.loadedLevelName);
    }
  3. GameManagerスクリプトを保存します。

これによってPlayerManagerlocalPlayerの既存インスタンスを参照をしない場合のみ、インスタンス化するようになります。

Back To Top

アリーナ外でプレイヤーの位置を管理

もう1つ留意すべき点があります。 アリーナのサイズはプレイヤーの数にもとづいて変化します。つまり、一人のプレイヤーが退室して他のプレイヤーが現在のアリーナサイズの限界に近づいた場合、読み込み時に小さいほうのアリーナの外に出てしまうことがあります。この場合はプレイヤーをアリーナの中心に戻す必要があります。これは、ゲームプレイやレベルの設計に特有の問題です。

現在、Unityが「シーン管理」を改良したばかりで、またUnity 5.4では一部のコールバックが軽視されているため、すべてのUnityバージョン(Unity 4.7から最新まで)で作動するコードを作成することは若干難しくなっています。このため、Unityバージョンに応じて異なるコードが必要です。

1.PlayerManagerスクリプトを開きます。 2. Start()メソッドの最後に以下のコードを追加します。

    #if UNITY54ORNEWER
    // Unity 5.4 has a new scene management. register a method to call CalledOnLevelWasLoaded.
    UnityEngine.SceneManagement.SceneManager.sceneLoaded += (scene, loadingMode) =>
            {
                this.CalledOnLevelWasLoaded(scene.buildIndex);
            };
   #endif

3.「MonoBehaviour CallBacks」リージョンに以下の2つのメソッドを追加します。

    #if !UNITY54ORNEWER
   /// <summary>See CalledOnLevelWasLoaded. Outdated in Unity 5.4.</summary>
   void OnLevelWasLoaded(int level)
   {
       this.CalledOnLevelWasLoaded(level);
   }
   #endif

void CalledOnLevelWasLoaded(int level) { // check if we are outside the Arena and if it's the case, spawn around the center of the arena in a safe zone if (!Physics.Raycast(transform.position, -Vector3.up, 5f)) { transform.position = new Vector3(0f, 5f, 0f); } }

  1. PlayerManagerスクリプトを保存します。

この新しいコードによって、読み込まれるレベルが監視されるのに加えて、プレイヤーの現在の位置が下方に再計算されてなにかに衝突するか確認されます。 衝突しない場合にはアリーナの地面にいないことを意味し、中央に再配置される必要があります。これは、ルームに初めて入室した場合とちょうど同様です。

Unity 5.4以下のUnityバージョンを使用している場合には、UnityのコールバックOnLevelWasLoadedを使用します。

Unity 5.4以上を使用している場合、OnLevelWasLoaded今後使用できません。その代わりに、新しいSceneManagementシステムを利用する必要があります。 最後に、コードの複製を防ぐためOnLevelWasLoadedまたはSceneManager.sceneLoadedコールバックから呼ばれるCalledOnLevelWasLoadedメソッドがあります。

次に進む
前に戻る

ドキュメントのトップへ戻る