Client can't move despite having ClientNetworkTransform!

My client won’t move despite having a ClientNetworkTransform attached to it.

And I can’t move my camera at all from client.

Though all animations like firing, moving, aiming, etc work fine on both host and client.

I am using the package Low Poly Shooter Pack - Free Sample | Systems | Unity Asset Store and I am trying to make a multiplayer shooter game using the fps package above that I modified a little bit and NGO.

We can’t advise without seeing any code and/or prefab setup. :wink:

@CodeSmile Sorry I forgot to attach any related items.

that’s the player movement script from the pack that I modified to fit my needs

// Copyright 2021, Infima Games. All Rights Reserved.

using System.Linq;
using UnityEngine;
using UnityEngine.InputSystem;

namespace InfimaGames.LowPolyShooterPack
{
    [RequireComponent(typeof(Rigidbody), typeof(CapsuleCollider))]
    public class Movement : MovementBehaviour
    {
        #region FIELDS SERIALIZED

        [Header("Audio Clips")]
      
        [Tooltip("The audio clip that is played while walking.")]
        [SerializeField]
        private AudioClip audioClipWalking;

        [Tooltip("The audio clip that is played while running.")]
        [SerializeField]
        private AudioClip audioClipRunning;

        [Header("Speeds")]

        [SerializeField]
        private float speedWalking = 5.0f;

        float speedRunningOriginal;

        [Tooltip("How fast the player moves while running."), SerializeField]
        private float speedRunning = 9.0f;

        [SerializeField] float speedSprinting = 12f;

        [SerializeField] float slideForce;

        [SerializeField] PlayerInput input;

        [SerializeField] GameObject cam;
        [SerializeField] GameObject minimapCam;
        [SerializeField] GameObject depthCam;
      
        #endregion

        #region PROPERTIES

        //Velocity.
        private Vector3 Velocity
        {
            //Getter.
            get => rigidBody.velocity;
            //Setter.
            set => rigidBody.velocity = value;
        }

        #endregion

        #region FIELDS

        /// <summary>
        /// Attached Rigidbody.
        /// </summary>
        private Rigidbody rigidBody;
        /// <summary>
        /// Attached CapsuleCollider.
        /// </summary>
        private CapsuleCollider capsule;
        /// <summary>
        /// Attached AudioSource.
        /// </summary>
        private AudioSource audioSource;
      
        /// <summary>
        /// True if the character is currently grounded.
        /// </summary>
        private bool grounded;

        /// <summary>
        /// Player Character.
        /// </summary>
        private CharacterBehaviour playerCharacter;
        /// <summary>
        /// The player character's equipped weapon.
        /// </summary>
        private WeaponBehaviour equippedWeapon;
      
        /// <summary>
        /// Array of RaycastHits used for ground checking.
        /// </summary>
        private readonly RaycastHit[] groundHits = new RaycastHit[8];

        #endregion

        #region UNITY FUNCTIONS

        public override void OnNetworkSpawn() {
            base.OnNetworkSpawn();

            if(!IsOwner) {
                cam.SetActive(false);
                minimapCam.SetActive(false);
                depthCam.SetActive(false);

                enabled = false;
            }
            else {
                input.enabled = true;
                playerCharacter = ServiceLocator.Current.Get<IGameModeService>().GetPlayerCharacter();

              
            }
        }

        /// <summary>
        /// Awake.
        /// </summary>
        protected override void Awake()
        {
            //Get Player Character.
          
        }

        /// Initializes the FpsController on start.
        protected override  void Start() {//Rigidbody Setup.
            SetupFPSController();

        }

        void SetupFPSController() {
            rigidBody = GetComponent<Rigidbody>();
            rigidBody.constraints = RigidbodyConstraints.FreezeRotation;
            //Cache the CapsuleCollider.
            capsule = GetComponent<CapsuleCollider>();

            //Audio Source Setup.
            audioSource = GetComponent<AudioSource>();
            audioSource.clip = audioClipWalking;
            audioSource.loop = true;

            speedRunningOriginal = speedRunning;
        }

        /// Checks if the character is on the ground.
        private void OnCollisionStay()
        {
            if(capsule == null) {
                SetupFPSController();
                return;
            }

            //Bounds.
            Bounds bounds = capsule.bounds;
            //Extents.
            Vector3 extents = bounds.extents;
            //Radius.
            float radius = extents.x - 0.01f;
          
            //Cast. This checks whether there is indeed ground, or not.
            Physics.SphereCastNonAlloc(bounds.center, radius, Vector3.down,
                groundHits, extents.y - radius * 0.5f, ~0, QueryTriggerInteraction.Ignore);
          
            //We can ignore the rest if we don't have any proper hits.
            if (!groundHits.Any(hit => hit.collider != null && hit.collider != capsule))
                return;
          
            //Store RaycastHits.
            for (var i = 0; i < groundHits.Length; i++)
                groundHits[i] = new RaycastHit();

            //Set grounded. Now we know for sure that we're grounded.
            grounded = true;
        }
          
        protected override void FixedUpdate()
        {
            //Move.
            MoveCharacter();
          
            //Unground.
            grounded = false;
        }

        /// Moves the camera to the character, processes jumping and plays sounds every frame.
        protected override void Update()
        {
            //Get the equipped weapon!
            equippedWeapon = playerCharacter.GetInventory().GetEquipped();
          
            //Play Sounds!
            PlayFootstepSounds();

            if (Input.GetKeyDown(KeyCode.Space)) {
                Jump();
            }

            if (Input.GetKeyDown(KeyCode.Z)) {
                Slide();
            }

            if (speedRunning > speedRunningOriginal) {
                speedRunning -= Time.deltaTime * slideForce * slideForce * (slideForce / 1.2f);
                transform.GetChild(0).GetComponent<Animator>().SetBool("Running", false);
              
            }
            else {
                sliding = false;
            }

            if (speedRunning < speedRunningOriginal) {
                speedRunning = speedRunningOriginal;
            }
        }

        #endregion

        #region METHODS

        private void MoveCharacter()
        {
            #region Calculate Movement Velocity

            //Get Movement Input!
            Vector2 frameInput = playerCharacter.GetInputMovement();
            //Calculate local-space direction by using the player's input.
            var movement = new Vector3(frameInput.x, 0.0f, frameInput.y);
          
            //Running speed calculation.
            if(playerCharacter.IsRunning())
                movement *= speedRunning;
            else if (playerCharacter.IsSprinting()) {
                movement *= speedSprinting;
            }
            else
            {
                //Multiply by the normal walking speed.
                movement *= speedWalking;
            }

            //World space velocity calculation. This allows us to add it to the rigidbody's velocity properly.
            movement = transform.TransformDirection(movement);

            #endregion
          
            //Update Velocity.
            Velocity = new Vector3(movement.x, Velocity.y, movement.z);
        }

        /// <summary>
        /// Plays Footstep Sounds. This code is slightly old, so may not be great, but it functions alright-y!
        /// </summary>
        private void PlayFootstepSounds()
        {
            //Check if we're moving on the ground. We don't need footsteps in the air.
            if (grounded && rigidBody.velocity.sqrMagnitude > 0.1f)
            {
                //Select the correct audio clip to play.
                audioSource.clip = playerCharacter.IsRunning() ? audioClipRunning : audioClipWalking;
                //Play it!
                if (!audioSource.isPlaying)
                    audioSource.Play();
            }
            //Pause it if we're doing something like flying, or not moving!
            else if (audioSource.isPlaying)
                audioSource.Pause();
        }

        bool sliding = false;

        void Slide() {
            if (sliding) return;


            speedRunning *= slideForce;
            transform.GetChild(0).GetComponent<Animator>().SetBool("Running", false);
            transform.GetChild(0).GetComponent<Animator>().SetBool("Sprinting", false);

            sliding = true;
        }

        [SerializeField] float jumpForce;

        void Jump() {

            if (!grounded) return;
          
            rigidBody.AddForce(transform.up * jumpForce);
          
        }
      
        #endregion
    }
}

@CodeSmile
these are the components on my network player
I enable the Player Input class when the player spawns and if is the owner as you can see in above code in line 108

this is the prefab

9743002--1393936--upload_2024-4-1_20-7-58.png

and i have the animator and some other scripts here

9743005--1393939--upload_2024-4-1_20-10-21.png

I suppose the camera is somewhere inside the player prefab? If not then that might be a problem.

Client is updating the Velocity value when it tries to move? Debug.Log or, well, debug (attach debugger, set breakpoint, step through code, see all values as the code runs, mind-blowing revelation if you haven’t done that before).

Since this code relies on a Rigidbody, you may need to add the NetworkRigidbody component too.

@CodeSmile Yes, the camera is inside the player prefab
And I also have the NetworkRigidbody

Though I will try to debug the code and find any issues in there!

@CodeSmile I did some debugging and found out that on the client side, the velocity is logged as 0 on all axes

On host side, the velocity log is as usual

Ok, I figured it out!

Actually, on the client side, the player character on the Movement script was set to the host.
As the host wasn’t moving when I tested the client, the movement input was zero.

Now I fixed it and everything works fine!
Thanks!

1 Like