Unity Photon PUN客户端移动卡顿且无法跳跃问题求助
问题解决:Unity + Photon PUN 客户端移动慢、无法跳跃
问题背景
使用Unity和Photon PUN开发多人游戏,已完成玩家移动与网络功能搭建,但出现客户端玩家移动速度慢于主机、且无法跳跃的问题。
已尝试方案
- 在Update和FixedUpdate中添加
if (!view.IsMine) return; - 同步Velocity
- 移除Photon Rigidbody View
- 使用Photon Transform View Classic替代普通版本
(以上操作重复尝试多次)
相关代码
玩家移动代码
private void Update() { input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")); input.Normalize(); isSprinting = Input.GetKey(KeyCode.LeftShift) && input.magnitude > 0.5f; isJumping = Input.GetKey(KeyCode.Space); } private void OnTriggerEnter(Collider other) { isGrounded = true; } private void OnTriggerExit(Collider other) { isGrounded = false; } private void FixedUpdate() { if (isGrounded) { if (isJumping) { rb.linearVelocity = new Vector3(rb.linearVelocity.x, jumpForce, rb.linearVelocity.z); } else if (input.magnitude > 0.5f) rb.AddForce(CalculateMovement(isSprinting ? runSpeed : walkSpeed), ForceMode.VelocityChange); else { var _velocity = rb.linearVelocity; _velocity = new Vector3(_velocity.x * 0.2f * Time.fixedDeltaTime, _velocity.y, _velocity.z * 0.2f * Time.fixedDeltaTime); rb.linearVelocity = _velocity; } } else { if (input.magnitude > 0.5f) rb.AddForce(CalculateMovement(isSprinting ? runSpeed * airControl : walkSpeed * airControl), ForceMode.VelocityChange); else { var _velocity = rb.linearVelocity; _velocity = new Vector3(_velocity.x * 0.2f * Time.fixedDeltaTime, _velocity.y, _velocity.z * 0.2f * Time.fixedDeltaTime); rb.linearVelocity = _velocity; } } } Vector3 CalculateMovement(float _speed) { Vector3 _targetVelocity = new Vector3(input.x, 0, input.y); _targetVelocity = transform.TransformDirection(_targetVelocity); _targetVelocity *= _speed; Vector3 _velocity = rb.linearVelocity; if (input.magnitude > 0.5f) { Vector3 _velcoityChange = _targetVelocity - _velocity; _velcoityChange.x = Mathf.Clamp(_velcoityChange.x, -maxVelocityChange, maxVelocityChange); _velcoityChange.z = Mathf.Clamp(_velcoityChange.z, -maxVelocityChange, maxVelocityChange); _velcoityChange.y = 0; return (_velcoityChange); } else { return new Vector3(); } }
Room Manager代码
public override void OnJoinedRoom() { base.OnJoinedRoom(); Debug.Log("Player joined room"); GameObject _player = PhotonNetwork.Instantiate(playerPrefab.name, spawnPoint.position, Quaternion.identity); _player.GetComponent<PlayerSetup>().IsLocalPlayer(); }
Player Start代码
public void IsLocalPlayer() { movement.enabled = true; camera.SetActive(true); }
解决方案
1. 修正本地玩家判断逻辑
手动调用IsLocalPlayer()存在风险,改用Photon自带的IsLocalPlayer属性自动判断,确保只有本地玩家执行移动逻辑:
private PhotonView photonView; private void Awake() { photonView = GetComponent<PhotonView>(); } private void Start() { if (photonView.IsMine) { IsLocalPlayer(); } else { movement.enabled = false; } }
2. 强制FixedUpdate仅本地执行
在移动脚本的FixedUpdate最开头添加本地玩家判断,避免客户端执行不必要的刚体操作:
private void FixedUpdate() { if (!photonView.IsMine) return; // 新增此行 // 原移动逻辑保留 }
3. 修复地面检测的网络同步问题
isGrounded是本地状态,不会自动同步到其他客户端,需确保跳跃逻辑仅由本地玩家处理:
- 保留本地玩家的地面检测逻辑,无需同步该状态
- 配置Photon组件仅同步本地玩家的位置、速度到其他客户端
4. 修正减速逻辑的时间步错误
ForceMode.VelocityChange已基于固定时间步计算,重复乘以Time.fixedDeltaTime会导致速度异常,修改减速代码:
// 原代码 _velocity = new Vector3(_velocity.x * 0.2f * Time.fixedDeltaTime, _velocity.y, _velocity.z * 0.2f * Time.fixedDeltaTime); // 修改后 _velocity = new Vector3(_velocity.x * 0.2f, _velocity.y, _velocity.z * 0.2f);
5. 优化Photon组件配置
- 使用PhotonRigidbodyView同步刚体的Velocity和AngularVelocity,同步模式设为
Only Stream Changed Properties - 将PhotonTransformView的插值模式设为
Interpolate,降低客户端位置延迟
内容的提问来源于stack exchange,提问作者Noah Bichsel
相关产品推荐
相关产品推荐

