背景
以前のUnity(具体的にこのバージョンまでというのはわかりません)では、Photon側の処理が遅く、Start()
メソッド内で PhotonNetwork.IsConnected
を確認してからプレイヤーのプレハブを生成していました。この順序により、プレイヤーが正しく同期されるようになっていました。しかし、最近のUnityでは、マルチスレッドや非同期処理の挙動が変更され、PhotonとUnityの処理順がより独立化されました。その結果、Start()
メソッド内でプレイヤーのプレハブを早い段階で生成すると、同期ずれが発生し、クライアント側のプレイヤーが見えなくなる(ホストのみ姿がみえ)という問題が発生しました。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun; //Photonサーバーの情報を使用するため
public class GameManager : MonoBehaviourPunCallbacks //Photon viewやPunを使用するため
{
public static GameManager Instance { get; private set; }
[SerializeField] GameObject playerPrefab;
// Start is called before the first frame update
void Start()
{
if(PhotonNetwork.IsConnected && PhotonNetwork.IsMasterClient) //サーバーに接続していたら
{
if(playerPrefab!=null)
{
Vector3 spawnPosition = new Vector3(0f, 0f, 0f);
PhotonNetwork.Instantiate(playerPrefab.name, spawnPosition, Quaternion.identity); //Photonを介した生成
}
}
}
}
問題の詳細
最近のUnityでは、非同期処理がより厳密に管理されるようになり、Start()
メソッド内でPhotonの同期処理を待たずにプレイヤーのプレハブが生成される場合があります。このタイミングの違いが原因で、プレイヤーオブジェクトの生成がPhotonのネットワーク同期処理よりも先行し、クライアント間で表示されるプレイヤーが異なったり、最終的にプレイヤーが見えなくなる現象が発生します。
影響
この問題は、プレイヤーが他のクライアントに表示されない、または同期が取れない状態を引き起こします。具体的には、プレイヤーの位置や動きが他のクライアントに反映されない、または一時的に見えなくなるという現象が発生します。特に、Start()
メソッド内でプレイヤーオブジェクトの生成と同期処理を行う場合、この同期のタイミングが非常に重要です。
解決策
各クライアントが自分のプレイヤを生成する
具体的には、OnJoinedRoom() メソッド内で PhotonNetwork.IsMasterClient が false の場合に、SpawnPlayer() を呼び出して、各クライアントが自分のプレイヤーを生成しています。このようにすることで、マスタークライアント以外のクライアントがプレイヤーの生成を行うことになります。さらに、プレイヤーの生成に PhotonNetwork.Instantiate を使っているので、他のクライアントにもそのプレイヤーオブジェクトが同期されます。
public override void OnJoinedRoom()
{
if (!PhotonNetwork.IsMasterClient)
{
// 各クライアントが自分のプレイヤを生成する
SpawnPlayer();
}
}
void SpawnPlayer()
{
if (playerPrefab != null && PhotonNetwork.IsConnected)
{
Vector3 spawnPosition = new Vector3(0f, 0f, 0f);
PhotonNetwork.Instantiate(playerPrefab.name, spawnPosition, Quaternion.identity);
}
}
結論
UnityのバージョンにおけるPhotonとUnityの処理順の変更により、プレイヤーオブジェクトの生成タイミングが重要になりました。Start()
メソッド内での処理順序に依存するのではなく、非同期処理を利用して適切な同期タイミングでプレイヤーオブジェクトを生成することが、同期ずれを防ぐために効果的な解決策となると思います。