PhotonNetwork.Instantiate异常:玩家对象无法实例化问题排查
问题排查与修复方案
核心问题分析
玩家无法实例化的根源在于两个脚本的异步逻辑处理错误,以及Photon网络流程的顺序违规,具体问题如下:
一、Photon_Manager脚本的关键错误
- 场景加载时机错误:调用
PhotonNetwork.CreateRoom()或PhotonNetwork.JoinRoom()后立刻执行场景加载,这两个操作是异步的,此时玩家并未真正加入房间,直接加载场景会导致后续网络状态异常。 - 协程使用无效:所有
StartCoroutine(waitSeconds())的调用都没有等待协程完成,代码直接继续执行,等待逻辑完全失效。 - UI切换时机错误:
LogIn()中调用PhotonNetwork.ConnectUsingSettings()后立刻切换到创建/加入房间UI,但此时网络连接尚未完成,后续房间操作可能失败。
二、Instantiate_Player脚本的关键错误
- 实例化逻辑未等待协程:
Start()中启动等待协程后直接执行玩家实例化判断,协程的等待没有生效,此时PhotonNetwork.IsConnectedAndReady可能仍为false,导致实例化代码不执行。 - 未确保预制体加载路径正确:
PhotonNetwork.Instantiate()要求预制体必须放在Resources文件夹下,否则无法找到预制体。
修复后的代码
1. 修改后的Photon_Manager脚本
using System.Collections; using TMPro; using UnityEngine; using UnityEngine.UI; using Photon.Pun; using Photon.Realtime; public class Photon_Manager : MonoBehaviourPunCallbacks { [SerializeField] TMP_InputField nameField; [SerializeField] TMP_InputField roomNameField; [SerializeField] TMP_InputField joinRoomField; [SerializeField] GameObject createJoinCanvas; [SerializeField] GameObject logInCanvas; [SerializeField] GameObject createCanvas; [SerializeField] GameObject joinCanvas; [SerializeField] string sceneToLoad; [SerializeField] public bool createRoomStatus = false; [SerializeField] public bool joinRoomStatus = false; [SerializeField] public bool logInStatus = false; public override void OnConnectedToMaster() { Debug.Log("Connected to master server"); PhotonNetwork.JoinLobby(); // 连接成功后再显示创建/加入房间UI logInCanvas.SetActive(false); createJoinCanvas.SetActive(true); logInStatus = true; Debug.Log("LogIn Done"); } public override void OnCreatedRoom() { Debug.Log("Created room: " + PhotonNetwork.CurrentRoom.Name); } // 加入房间成功后加载游戏场景 public override void OnJoinedRoom() { Debug.Log(PhotonNetwork.LocalPlayer.NickName + " joined " + PhotonNetwork.CurrentRoom.Name); StartCoroutine(WaitAndLoadScene(sceneToLoad)); // 根据操作类型更新UI与状态 if(createRoomStatus) { createCanvas.SetActive(false); } else if(joinRoomStatus) { joinCanvas.SetActive(false); } } void Start() { Debug.Log("Photon Manager started"); } public void LogIn() { string temp = nameField.text; if(!string.IsNullOrEmpty(temp)) { PhotonNetwork.LocalPlayer.NickName = temp; PhotonNetwork.ConnectUsingSettings(); logInCanvas.SetActive(false); } else { Debug.LogError("Nickname cannot be empty!"); } } public void CreateRoom() { string roomName = roomNameField.text; if(!string.IsNullOrEmpty(roomName)) { createRoomStatus = true; joinRoomStatus = false; PhotonNetwork.CreateRoom(roomName); } else { Debug.LogError("Room name cannot be empty!"); } } public void JoinRoom() { string tempRoomName = joinRoomField.text; if(!string.IsNullOrEmpty(tempRoomName)) { joinRoomStatus = true; createRoomStatus = false; PhotonNetwork.JoinRoom(tempRoomName); } else { Debug.LogError("Room name cannot be empty!"); } } // 带等待的场景加载协程 private IEnumerator WaitAndLoadScene(string sceneName) { yield return new WaitForSeconds(2.5f); PhotonNetwork.LoadLevel(sceneName); } }
2. 修改后的Instantiate_Player脚本
using UnityEngine; using Photon.Pun; using System.Collections; public class Instantiate_Player : MonoBehaviour { [SerializeField] GameObject playerPrefab; [SerializeField] float xMin; [SerializeField] float zMin; [SerializeField] float xMax; [SerializeField] float zMax; void Start() { // 将实例化逻辑放入协程,确保等待后执行 StartCoroutine(WaitAndSpawnPlayer()); } private IEnumerator WaitAndSpawnPlayer() { yield return new WaitForSeconds(1.5f); // 循环检查网络状态,直到就绪 while(!PhotonNetwork.IsConnectedAndReady) { yield return null; } // 确保预制体存在且在Resources文件夹中 if(playerPrefab != null) { Vector3 playerPos = new Vector3(Random.Range(xMin, xMax), 0.0f, Random.Range(zMin, zMax)); // 使用默认groupID 0 GameObject obj = PhotonNetwork.Instantiate(playerPrefab.name, playerPos, Quaternion.identity); obj.SetActive(true); Debug.Log("Player instantiated successfully"); } else { Debug.LogError("Player prefab is not assigned!"); } } }
额外注意事项
- 玩家预制体必须放置在Resources文件夹下,
PhotonNetwork.Instantiate()只能加载该目录下的资源。 - 预制体上的
PhotonView组件需正确配置:View ID设置为AutoSync,并将需要同步的组件(如移动脚本)添加到观察列表中。 - 检查PhotonServerSettings的App ID、Region等参数,确保与Photon Dashboard配置一致。
内容的提问来源于stack exchange,提问作者Omkar P
相关产品推荐
相关产品推荐

