You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中GameObject旋转在客户端与主机间不同步的问题求助

问题解决:客户端操作弓的旋转无法同步到主机

核心原因

你当前的问题是Weapon对象的所有权仍在主机端,即便添加了Client Network Transform组件,客户端没有对象所有权的情况下,对旋转的修改无法同步回服务器/主机。只有拥有所有权的客户端,其操作才能通过Client Network Transform同步到服务器及其他客户端。

解决方案步骤

1. 拿起弓时转移所有权给玩家

在InteractServerRpc中添加所有权转移逻辑,让拿起弓的玩家获得该Weapon的网络所有权:

[ServerRpc(RequireOwnership = false)]
private void InteractServerRpc(NetworkObjectReference interactedPlayerNetworkObjectReference)
{   
    if (interactedPlayerNetworkObjectReference.TryGet(out NetworkObject playerNetObj))
    {
        // 将武器所有权转移给拿起它的玩家
        NetworkObject.ChangeOwnership(playerNetObj.OwnerClientId);
    }
    InteractClientRpc(interactedPlayerNetworkObjectReference);
}

2. 调整旋转逻辑的判断条件

将HandlePlayerPossessionBehaviour中的attachedPlayer.IsLocalPlayer替换为IsOwner,确保只有拥有武器所有权的客户端(当前持有武器的玩家)才处理旋转:

private void HandlePlayerPossessionBehaviour()
{
    if (attachedPlayerGameObject == null) return;

    transform.position = attachedPlayerGameObject.transform.position;

    // 仅拥有所有权的客户端处理旋转
    if (IsOwner)
    {
        FollowPlayerMousePointer();
    }
}

3. 确认Client Network Transform配置

检查Weapon对象上的Client Network Transform组件:

  • 确保Sync Z Rotation已勾选
  • 确认Owner Auth选项处于勾选状态(默认开启,此选项表示所有权持有者的修改会同步到服务器)

完整修改后的Weapon代码

using Unity.Netcode;
using UnityEngine;

public class Weapon : NetworkBehaviour, IInteractable
{
    [SerializeField] private GameObject attachedPlayerGameObject;
    [SerializeField] private Player attachedPlayer;
    [SerializeField] private bool isOnPossession = false;

    private void LateUpdate()
    {
        if (!isOnPossession) return;
        HandlePlayerPossessionBehaviour();
    }

    public void Interact(Player interactedPlayer)
    {
        InteractServerRpc(interactedPlayer.GetNetworkObject());
    }

    [ServerRpc(RequireOwnership = false)]
    private void InteractServerRpc(NetworkObjectReference interactedPlayerNetworkObjectReference)
    {   
        if (interactedPlayerNetworkObjectReference.TryGet(out NetworkObject playerNetObj))
        {
            // 转移武器所有权给拿起它的玩家
            NetworkObject.ChangeOwnership(playerNetObj.OwnerClientId);
        }
        InteractClientRpc(interactedPlayerNetworkObjectReference);
    }

    [ClientRpc]
    private void InteractClientRpc(NetworkObjectReference interactedPlayerNetworkObjectReference)
    {
        interactedPlayerNetworkObjectReference.TryGet(out NetworkObject interactedPlayerNetworkObject);
        Player interactedPlayer = interactedPlayerNetworkObject.GetComponent<Player>();
        
        attachedPlayer = interactedPlayer;
        attachedPlayerGameObject = interactedPlayer.gameObject;
        isOnPossession = true;
    }

    private void HandlePlayerPossessionBehaviour()
    {
        if (attachedPlayerGameObject == null) return;

        transform.position = attachedPlayerGameObject.transform.position;

        // 仅拥有所有权的客户端处理旋转
        if (IsOwner)
        {
            FollowPlayerMousePointer();
        }
    }

    private void FollowPlayerMousePointer()
    {
        Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        Vector2 lookDir = mousePos - new Vector2(transform.position.x, transform.position.y);
        float angle = Mathf.Atan2(lookDir.y, lookDir.x) * Mathf.Rad2Deg;
        transform.eulerAngles = new Vector3(0f, 0f, angle);
    }
}

额外说明

  • 所有权转移是Netcode for GameObjects中客户端修改同步的核心逻辑,只有拥有所有权的对象,客户端的修改才会被服务器认可并同步给其他客户端。
  • 你的Player移动逻辑目前是客户端直接修改位置,建议给Player也添加Client Network Transform组件,让移动同步更可靠(此为额外优化,与当前弓的旋转问题无关)。

内容的提问来源于stack exchange,提问作者Alexandre Carneiro da Silva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 10:29:57