Unity Photon中玩家加入/重连时多实例问题的修复方法
问题分析
你遇到的重复玩家实例问题,核心原因是每次加载场景(从小游戏返回房间、重连/新玩家加入)时,都无条件执行PhotonNetwork.Instantiate生成玩家,但Photon在场景切换后会保留房间的玩家状态,导致重复生成;同时未判断本地玩家是否已有实例,进而出现多个实例,仅最新生成的实例因为是本地玩家的有效Owner,所以能被控制。
修复方案
1. 避免重复生成本地玩家实例
修改两个场景中的SpawnPlayers方法,添加检查逻辑,仅当本地玩家在当前场景中没有实例时才生成:
房间场景的SpawnPlayers修改:
// For the Room Scene // After joining the room void SpawnPlayers() { // 遍历场景中所有PhotonView,检查是否已有本地玩家的实例 foreach (PhotonView pv in FindObjectsOfType<PhotonView>()) { if (pv.Owner.IsLocal) { return; // 本地玩家已有实例,直接返回,不再生成 } } Vector2 position = new(Random.Range(minX, maxX), Random.Range(minY, maxY)); PhotonNetwork.Instantiate(playerPrefab.name, position, Quaternion.identity); }
小游戏场景的SpawnPlayers修改:
// For the Minigame Scene // After joining the minigame void SpawnPlayers() { // 同样检查本地玩家是否已有实例 foreach (PhotonView pv in FindObjectsOfType<PhotonView>()) { if (pv.Owner.IsLocal) { return; } } Vector2 position = new(Random.Range(min.x, max.x), Random.Range(min.y, max.y)); PhotonNetwork.Instantiate(playerPrefab.name, position, Quaternion.identity); }
2. 调整SpawnPlayers的调用时机
不要在场景的Start/Awake中直接调用SpawnPlayers,而是放在Photon的房间回调中,确保仅在首次加入房间或重连后确认无实例时调用:
在继承自MonoBehaviourPunCallbacks的脚本中,重写以下方法:
public override void OnJoinedRoom() { base.OnJoinedRoom(); SpawnPlayers(); // 仅在成功加入房间时生成玩家 } public override void OnPlayerJoinedRoom(Player newPlayer) { base.OnPlayerJoinedRoom(newPlayer); // 如果是本地玩家重连,检查是否需要生成实例 if (newPlayer.IsLocal) { SpawnPlayers(); } }
3. 确保玩家控制脚本仅在本地实例生效
在玩家的移动控制脚本中添加判断,仅本地玩家的实例启用控制逻辑:
void Start() { PhotonView pv = GetComponent<PhotonView>(); if (!pv.IsMine) { // 非本地玩家实例,禁用控制组件 enabled = false; return; } // 本地玩家实例,正常启用控制 }
额外注意事项
- 确保玩家预制体上的
PhotonView组件设置正确,View ID设为AutoGenerate。 - 使用
PhotonNetwork.LoadLevel时,开启PhotonServerSettings中的AutoSyncScene,保证所有客户端同步加载场景,避免状态不一致。
内容的提问来源于stack exchange,提问作者Ellie
相关产品推荐
相关产品推荐

