Unity Photon多人游戏如何实现不同玩家物体同时独立旋转同步
问题根因
当前枪械旋转脚本未做Photon网络所有权校验,所有客户端运行时,无论枪械归属哪个玩家,都会直接读取本地鼠标输入修改所有枪械对象的Transform;同时本地修改的远端玩家枪械状态,会持续被Photon下发的远端同步数据覆盖,最终出现所有枪械都跟随本地鼠标旋转、多端状态不同步的异常。
修复逻辑
遵循Photon多人开发的核心规则:仅对象的所属客户端有权限修改该网络对象的状态,其余客户端只接收网络同步的状态数据,不做本地输入驱动的修改,按以下步骤调整:
- 确认玩家预制体、枪械子物体上正确挂载
PhotonView组件,枪械的旋转、位置参数加入PhotonView的同步观测列表 - 在枪械旋转脚本中增加所有权判断,仅当枪械归属本地玩家时,才执行鼠标输入读取、旋转计算、Transform修改逻辑
- 远端玩家的枪械不执行任何本地控制逻辑,直接渲染Photon同步过来的旋转、位置状态即可
修复后参考代码
using System.Collections; using System.Collections.Generic; using UnityEngine; using Photon.Pun; public class gunRotation : MonoBehaviour { bool nf; bool f; bool l = true; private PhotonView pv; void Start() { // 枪械为玩家子物体时,获取父节点上的PhotonView组件;若枪械自身挂载PhotonView,可直接GetComponent<PhotonView>() pv = GetComponentInParent<PhotonView>(); } public void FixedUpdate() { // 非本地玩家所属枪械,直接跳过本地控制逻辑,等待网络同步状态 if (!pv.IsMine) return; //rotates the gun Vector3 difference = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position; float rotationZ = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg; difference.Normalize(); transform.rotation = Quaternion.Euler(0f, 0f, rotationZ); if (rotationZ < -90 || rotationZ > 90) { if (gameObject.transform.eulerAngles.y == 0) { transform.localRotation = Quaternion.Euler(180, 0, -rotationZ); } else if (gameObject.transform.eulerAngles.y == 180) { transform.localRotation = Quaternion.Euler(180, 180, -rotationZ); } } // helps gun switch pos if (gameObject.transform.eulerAngles.y == 0 && l == true) { nf = true; l = false; } // switch gun pos if (gameObject.transform.eulerAngles.y == 0 && nf == true) { transform.position = new Vector3(gameObject.transform.position.x + 1.123f, gameObject.transform.position.y, gameObject.transform.position.z); nf = false; f = true; } else if (gameObject.transform.eulerAngles.y == 180 && f == true) { transform.position = new Vector3(gameObject.transform.position.x - 1.123f, gameObject.transform.position.y, gameObject.transform.position.z); f = false; nf = true; } } }
额外注意事项
所有玩家输入驱动的逻辑(移动、射击、道具交互等)都必须加
PhotonView.IsMine判断,禁止非所属客户端修改网络对象状态,否则会持续出现状态冲突、同步抖动、逻辑异常的问题。如果需要低延迟的远端表现,可以单独做客户端侧的预测插值,不要直接修改同步目标的Transform值。
内容的提问来源于stack exchange,提问作者Creamy
相关产品推荐
相关产品推荐

