Photon多人系统中Start()被调用两次的问题求助
问题解决:Photon多人游戏中Start()重复调用导致的日志/实例化重复
核心原因
- 每个客户端加载场景时,都会执行场景中
MPRoomServer脚本的Start()方法,而PhotonNetwork.Instantiate是网络同步方法,会在所有客户端创建实例,叠加后导致重复。 - 若
MPRoomServer所在GameObject带有PhotonView组件,Photon可能会在网络同步时生成该对象的副本,导致脚本被两次初始化。
解决方案
方案1:仅让Master Client执行全局实例化逻辑
火箭这类全局场景对象,只需要由房间的Master Client创建一次,所有客户端会自动同步该实例。修改Start()方法,加入Master Client判断:
using System.Collections; using System.Collections.Generic; using UnityEngine; using Photon.Pun; using TMPro; public class MPRoomServer : MonoBehaviour { public GameObject rocket; public TMP_Text title; void Start() { // 仅在Master Client执行全局实例化 if (PhotonNetwork.IsMasterClient) { PhotonNetwork.Instantiate(rocket.name, new Vector3(20.4928417f,4.3900001f,-10.116004f), Quaternion.identity); } // 每个客户端仅更新自己本地的UI title.text = "Room " + PhotonNetwork.CurrentRoom.Name; // 仅在本地客户端打印日志,避免重复输出 Debug.Log($"Local player joined: {PhotonNetwork.LocalPlayer.NickName}"); } }
方案2:避免场景对象的网络重复同步
如果MPRoomServer所在GameObject带有PhotonView组件,需要:
- 确保该对象的
PhotonView组件中,Instantiation设置为"Manual Instantiation" - 或者移除
PhotonView组件,将该对象标记为只在本地存在,仅让每个客户端独立处理本地UI逻辑,全局实例化逻辑交给Master Client。
方案3:使用Photon的回调替代Start()
改用Photon提供的网络回调方法,比如OnJoinedRoom(),确保逻辑只在玩家成功加入房间时执行一次:
using System.Collections; using System.Collections.Generic; using UnityEngine; using Photon.Pun; using Photon.Realtime; using TMPro; public class MPRoomServer : MonoBehaviourPunCallbacks { public GameObject rocket; public TMP_Text title; void Start() { // 保留本地UI初始化,避免依赖回调时机 title.text = "Room " + PhotonNetwork.CurrentRoom.Name; } // 玩家成功加入房间时的回调,仅执行一次 public override void OnJoinedRoom() { if (PhotonNetwork.IsMasterClient) { PhotonNetwork.Instantiate(rocket.name, new Vector3(20.4928417f,4.3900001f,-10.116004f), Quaternion.identity); } Debug.Log($"New player joined: {PhotonNetwork.LocalPlayer.NickName}"); } }
关键注意点
PhotonNetwork.Instantiate会自动在所有客户端同步创建对象,不要在每个客户端都调用,否则会导致N个客户端创建N次,最终出现N²个实例。- 区分全局逻辑(仅Master Client执行)和本地逻辑(每个客户端执行),避免重复执行。
内容的提问来源于stack exchange,提问作者user17833773
相关产品推荐
相关产品推荐

