Search code examples
unity-game-enginegame-developmentmultiplayernetcode

Why does the rotation of my gameobject not syncronize between client and host?


I needed my bow to rotate towards my mouse, however even though I have attached a client network transform to it and allowed it to synchronize the z-axis rotation, it only works on the host (if I rotate on the host is appears on the client but not the other way around).

This is the code for my Player character:

using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;
using Collider2D = UnityEngine.Collider2D;

public class Player : NetworkBehaviour
{
    public static Player LocalInstance { get; private set; }
    
    [SerializeField] private float speed;

    private Collider2D[] playerColliders;

    private void Awake()
    {
        playerColliders = GetComponents<Collider2D>();
    }
    
    private void Start()
    {
        GameInput.Instance.OnInteractAction += HandleInteraction;
    }
    
    public override void OnNetworkSpawn()
    {
        if (IsOwner) 
           LocalInstance = this;
    }
    
    private void Update()
    {
        HandleMovement();
    }

    private void HandleInteraction(object sender, System.EventArgs e)
    {
        List<Collider2D> contactColliders = new List<Collider2D>();
        bool hasInteracted = false;
        
        foreach (Collider2D playerCollider in playerColliders)
        {
            Physics2D.OverlapCollider(playerCollider, contactColliders);

            foreach (Collider2D contactCollider in contactColliders)
            {
                if (!contactCollider.gameObject.TryGetComponent<IInteractable>(out IInteractable interactable)) 
                   continue;
                    
                interactable.Interact(this);
                hasInteracted = true;
                break;
            }

            if (hasInteracted) break;
        }
    }
    
    private void HandleMovement()
    {
        Vector2 direction = GameInput.Instance.GetDirectionVector();
        
        transform.position += (Vector3)(direction * (speed * Time.deltaTime));
    }

    public NetworkObject GetNetworkObject()
    {
        return NetworkObject;
    }
}

this is the code for my bow:

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)
    {   
        
        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 (attachedPlayer.IsLocalPlayer)
        {
            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);
    }
}


Solution

  • The solution for this problem was changing the ownership of the bow object to match the ownership of the client like this:

    private void InteractServerRpc(NetworkObjectReference interactedPlayerNetworkObjectReference, ulong clientId)
    {   
        NetworkObject.ChangeOwnership(clientId);
        InteractClientRpc(interactedPlayerNetworkObjectReference);
    }