使用Photon-PUN开发多人游戏时Player1无法看到Player2的问题
问题解决指南
问题1:创建房间的Player1无法看到加入的Player2
核心原因
Player预制体未放置在Resources目录下,导致其他客户端无法通过PhotonNetwork.Instantiate加载并生成玩家实例;或Player预制体缺失PhotonView组件,无法完成网络同步。
修复步骤
- 调整预制体路径
- 在Unity项目中创建
Resources文件夹(若不存在),将Player预制体移入该文件夹。PhotonNetwork.Instantiate仅能加载Resources目录下的资源,否则其他客户端无法生成对应玩家实例。
- 在Unity项目中创建
- 配置PhotonView组件
- 给Player预制体添加
PhotonView组件:- 在"Observed Components"列表中添加
PlayerController,让Photon自动同步该组件的序列化数据。 - 确保PhotonView的"View ID"设置为"Auto Assign"(默认值即可)。
- 在"Observed Components"列表中添加
- 给Player预制体添加
问题2:移动Player2时触发Received OnSerialization for view ID XXXX警告
核心原因
Player1客户端未生成Player2的实例,导致收到Player2的同步数据时找不到对应PhotonView;同时未实现玩家位置/旋转的网络同步逻辑,引发序列化异常。
修复步骤
- 实现IPunObservable接口同步玩家状态
修改PlayerController代码,添加位置和旋转的网络同步逻辑,确保远程客户端能正确同步玩家移动:
using UnityEngine; using Photon.Pun; public class PlayerController : MonoBehaviourPunCallbacks, IPunObservable { public float speed; public float rotSpeed; private Vector3 targetPosition; private Quaternion targetRotation; void Start() { if (!photonView.IsMine) { GetComponentInChildren<Camera>().enabled = false; GetComponentInChildren<AudioListener>().enabled = false; targetPosition = transform.position; targetRotation = transform.rotation; } } void Update() { if (photonView.IsMine) { // 本地玩家移动逻辑保持不变 if (Input.GetKey(KeyCode.W)) transform.position += transform.forward * speed * Time.deltaTime; if (Input.GetKey(KeyCode.S)) transform.position += -transform.forward * speed * Time.deltaTime; if (Input.GetKey(KeyCode.A)) transform.Rotate(0, -rotSpeed * Time.deltaTime, 0); if (Input.GetKey(KeyCode.D)) transform.Rotate(0, rotSpeed * Time.deltaTime, 0); } else { // 平滑同步远程玩家的位置和旋转 transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * 5f); transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, Time.deltaTime * 5f); } } // 实现序列化同步逻辑 public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) { if (stream.IsWriting) { // 本地玩家发送位置和旋转数据 stream.SendNext(transform.position); stream.SendNext(transform.rotation); } else { // 远程玩家接收并存储同步数据 targetPosition = (Vector3)stream.ReceiveNext(); targetRotation = (Quaternion)stream.ReceiveNext(); } } }
- 修正NetworkManager连接逻辑
原代码中连接后立刻判断PhotonNetwork.IsConnected是异步操作的错误用法,修改为在回调中确认连接:
public void Connect(){ if (!PhotonNetwork.IsConnected) { PhotonNetwork.ConnectUsingSettings(); } } public override void OnConnectedToMaster(){ Debug.Log("Server Connected"); PhotonNetwork.JoinLobby(); }
额外检查项
- 确保所有客户端使用相同的Photon App ID,避免跨服务器连接。
- 游戏场景加载完成后,
GameManager的Start方法会自动为每个客户端实例化本地玩家,无需额外修改该逻辑。
内容的提问来源于stack exchange,提问作者Rakesh Kr Yadav
相关产品推荐
相关产品推荐

