Joysticks isn't working for the client but for the host

Hi,
I'm developing a multiplayer Third person shooter game. The code was working from both host and client side while controlling from mouse/keyboard. Since, this will be a mobile multiplayer(android) game so I've added a "FixedJoysticks" to control game from mobile . But, the problem is that host can control his own player through the joysticks but client cannot, player is not moving for the client with the joysticks. On the other hand, client can move the player through joysticks when the host leaves. I don't know why this happened. I'm learning multiplayer but facing this problem. I have searched over the internet but still didn't get the solution. Hope you will help me in this case. Will be gladed.

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

public class ThirdpersonMovementNet : NetworkBehaviour
{
    public CharacterController controller;
    public Transform cam;
    public float speed;
    public float speed2 = 20f;
    public float turnSmoothTime = 0.1f;
    private float turnSmoothVelocity;

    [SerializeField] private float positionRange = 3f;
    [SerializeField] private float positionRangeUpwards = 1082.0626f;
    [SerializeField] private float positionRangeUpwards2 = 682.0626f;
    [SerializeField] private float gravity = -9.81f;
    [SerializeField] private float jumpHeight = 1.0f;

    [SerializeField] private Animator anim;
    private Vector3 velocity;
    private bool isGrounded;


    public Transform groundCheck;
    public float groundDistance = 0.4f;
    public LayerMask groundMask;

    public FixedJoystick fixedJoystick;

    /* public override void OnNetworkSpawn()
     {

    UpdatePosServerRpc();

}*/

    public override void OnNetworkSpawn()
    {
        if (IsServer)
        {
            Vector3 newPosition = new Vector3(Random.Range(-positionRange, positionRange), Random.Range(positionRangeUpwards, positionRangeUpwards2), Random.Range(-positionRange, positionRange));
            transform.position = newPosition;
            transform.rotation = Quaternion.Euler(0, 180, 0);
            UpdatePosClientRpc(newPosition);

        }

    }


    private void Start()
    {

     /*   Cursor.lockState = CursorLockMode.Locked;*/

    }

    void Update()
    {
        if (!IsOwner && !MyGManager.Instance.IsGamePlaying()) return;

        isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);

        if (isGrounded && velocity.y < 0)
        {
            velocity.y = -2f;
            anim.SetBool("ShouldFly", false);
            anim.SetBool("Parachute", false);
            if (anim.GetBool("ShouldJump"))
            {
                anim.SetBool("ShouldJump", false);
            }

            // Ensure the player goes back to idle when grounded
            if (!anim.GetBool("IsRunning"))
            {
                anim.SetBool("IsRunning", false);
            }
        }
        /*
                float horizontal = Input.GetAxisRaw("Horizontal");
                float vertical = Input.GetAxisRaw("Vertical");*/

        float horizontal = fixedJoystick.Horizontal;
        float vertical= fixedJoystick.Vertical;



        Vector3 dir = new Vector3(horizontal, 0f, vertical).normalized;

        if (dir.magnitude >= 0.1f)
        {
            float targetAngle = Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg + cam.eulerAngles.y;
            float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
            transform.rotation = Quaternion.Euler(0f, angle, 0f);
            Vector3 moveDir = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward;
            controller.Move(moveDir.normalized * speed * Time.deltaTime);
            anim.SetBool("IsRunning", true);
        }
        else
        {
            anim.SetBool("IsRunning", false);
        }

        if (isGrounded && Input.GetButtonDown("Jump"))
        {
            velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
            anim.SetBool("ShouldJump", true);
        }

        if (transform.position.y > 420 && velocity.y < 0)
        {
            anim.SetBool("ShouldFly", true);

            Vector3 moveDirection = cam.forward * vertical + cam.right * horizontal;
            moveDirection.y = 0f; // Ensure no vertical movement
            moveDirection.Normalize(); // Normalize to ensure consistent speed
            controller.Move(moveDirection * speed2 * Time.deltaTime);
        }
        else if (transform.position.y <= 420)
        {
            anim.SetBool("ShouldFly", false);
            anim.SetBool("Parachute", true);
        }

        // Ensure parachute animation stops when grounded
        if (isGrounded)
        {
            anim.SetBool("Parachute", false);
        }

        velocity.y += gravity * Time.deltaTime;
        controller.Move(velocity * Time.deltaTime);
    }


    [ServerRpc(RequireOwnership = false)]
    private void UpdatePosServerRpc(Vector3 newPosition)
    {
        UpdatePosClientRpc(newPosition);
    }

    [ClientRpc]
    private void UpdatePosClientRpc(Vector3 newPosition)
    {
        transform.position = newPosition;
        transform.rotation = Quaternion.Euler(0, 180, 0);
    }

}

Since this is Unity's Netcode there's a subforum specifically for NGO. ;)

You can just use NetworkTransform to sync positions. You don't have to manually write RPCs to do this.
Then you can make a subclass ClientAuthoritativeNetworkTransform which has the authority property overriden, so that the client can change the transform rather than the server.

Since you check for IsOwner the most likely cause seems to be that the client isn't actually the owner of the object.

When the host leaves the network session ends. Normally you'd reset the game at this point but I suppose here it just keeps on running offline and I can only assume that because of it the former client now has full authority over everything.

1 Like

Hello Everyone,
The problem is fixed. So I have checked ownership and initialized in OnNetworkSpawn().
Make sure you do the same thing

public override OnNetworkSpawn(){

if(IsOwner)
{
joysticks=FindFirstObjectByType
If(joysticks==null){
Debug.Log....
}
}

}

Note: I am using FixedJoysticks (from unity asset store) which is very popular for the mobile development.


Thank you