Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Resolved Client can't move despite having ClientNetworkTransform!

Discussion in 'Netcode for GameObjects' started by BKsingh2715, Apr 1, 2024.

  1. BKsingh2715

    BKsingh2715

    Joined:
    Sep 24, 2021
    Posts:
    17
    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.
     
    Last edited: Apr 1, 2024
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,892
    We can't advise without seeing any code and/or prefab setup. ;)
     
  3. BKsingh2715

    BKsingh2715

    Joined:
    Sep 24, 2021
    Posts:
    17
    @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

    Code (CSharp):
    1. // Copyright 2021, Infima Games. All Rights Reserved.
    2.  
    3. using System.Linq;
    4. using UnityEngine;
    5. using UnityEngine.InputSystem;
    6.  
    7. namespace InfimaGames.LowPolyShooterPack
    8. {
    9.     [RequireComponent(typeof(Rigidbody), typeof(CapsuleCollider))]
    10.     public class Movement : MovementBehaviour
    11.     {
    12.         #region FIELDS SERIALIZED
    13.  
    14.         [Header("Audio Clips")]
    15.      
    16.         [Tooltip("The audio clip that is played while walking.")]
    17.         [SerializeField]
    18.         private AudioClip audioClipWalking;
    19.  
    20.         [Tooltip("The audio clip that is played while running.")]
    21.         [SerializeField]
    22.         private AudioClip audioClipRunning;
    23.  
    24.         [Header("Speeds")]
    25.  
    26.         [SerializeField]
    27.         private float speedWalking = 5.0f;
    28.  
    29.         float speedRunningOriginal;
    30.  
    31.         [Tooltip("How fast the player moves while running."), SerializeField]
    32.         private float speedRunning = 9.0f;
    33.  
    34.         [SerializeField] float speedSprinting = 12f;
    35.  
    36.         [SerializeField] float slideForce;
    37.  
    38.         [SerializeField] PlayerInput input;
    39.  
    40.         [SerializeField] GameObject cam;
    41.         [SerializeField] GameObject minimapCam;
    42.         [SerializeField] GameObject depthCam;
    43.      
    44.         #endregion
    45.  
    46.         #region PROPERTIES
    47.  
    48.         //Velocity.
    49.         private Vector3 Velocity
    50.         {
    51.             //Getter.
    52.             get => rigidBody.velocity;
    53.             //Setter.
    54.             set => rigidBody.velocity = value;
    55.         }
    56.  
    57.         #endregion
    58.  
    59.         #region FIELDS
    60.  
    61.         /// <summary>
    62.         /// Attached Rigidbody.
    63.         /// </summary>
    64.         private Rigidbody rigidBody;
    65.         /// <summary>
    66.         /// Attached CapsuleCollider.
    67.         /// </summary>
    68.         private CapsuleCollider capsule;
    69.         /// <summary>
    70.         /// Attached AudioSource.
    71.         /// </summary>
    72.         private AudioSource audioSource;
    73.      
    74.         /// <summary>
    75.         /// True if the character is currently grounded.
    76.         /// </summary>
    77.         private bool grounded;
    78.  
    79.         /// <summary>
    80.         /// Player Character.
    81.         /// </summary>
    82.         private CharacterBehaviour playerCharacter;
    83.         /// <summary>
    84.         /// The player character's equipped weapon.
    85.         /// </summary>
    86.         private WeaponBehaviour equippedWeapon;
    87.      
    88.         /// <summary>
    89.         /// Array of RaycastHits used for ground checking.
    90.         /// </summary>
    91.         private readonly RaycastHit[] groundHits = new RaycastHit[8];
    92.  
    93.         #endregion
    94.  
    95.         #region UNITY FUNCTIONS
    96.  
    97.         public override void OnNetworkSpawn() {
    98.             base.OnNetworkSpawn();
    99.  
    100.             if(!IsOwner) {
    101.                 cam.SetActive(false);
    102.                 minimapCam.SetActive(false);
    103.                 depthCam.SetActive(false);
    104.  
    105.                 enabled = false;
    106.             }
    107.             else {
    108.                 input.enabled = true;
    109.                 playerCharacter = ServiceLocator.Current.Get<IGameModeService>().GetPlayerCharacter();
    110.  
    111.              
    112.             }
    113.         }
    114.  
    115.         /// <summary>
    116.         /// Awake.
    117.         /// </summary>
    118.         protected override void Awake()
    119.         {
    120.             //Get Player Character.
    121.          
    122.         }
    123.  
    124.         /// Initializes the FpsController on start.
    125.         protected override  void Start() {//Rigidbody Setup.
    126.             SetupFPSController();
    127.  
    128.         }
    129.  
    130.         void SetupFPSController() {
    131.             rigidBody = GetComponent<Rigidbody>();
    132.             rigidBody.constraints = RigidbodyConstraints.FreezeRotation;
    133.             //Cache the CapsuleCollider.
    134.             capsule = GetComponent<CapsuleCollider>();
    135.  
    136.             //Audio Source Setup.
    137.             audioSource = GetComponent<AudioSource>();
    138.             audioSource.clip = audioClipWalking;
    139.             audioSource.loop = true;
    140.  
    141.             speedRunningOriginal = speedRunning;
    142.         }
    143.  
    144.         /// Checks if the character is on the ground.
    145.         private void OnCollisionStay()
    146.         {
    147.             if(capsule == null) {
    148.                 SetupFPSController();
    149.                 return;
    150.             }
    151.  
    152.             //Bounds.
    153.             Bounds bounds = capsule.bounds;
    154.             //Extents.
    155.             Vector3 extents = bounds.extents;
    156.             //Radius.
    157.             float radius = extents.x - 0.01f;
    158.          
    159.             //Cast. This checks whether there is indeed ground, or not.
    160.             Physics.SphereCastNonAlloc(bounds.center, radius, Vector3.down,
    161.                 groundHits, extents.y - radius * 0.5f, ~0, QueryTriggerInteraction.Ignore);
    162.          
    163.             //We can ignore the rest if we don't have any proper hits.
    164.             if (!groundHits.Any(hit => hit.collider != null && hit.collider != capsule))
    165.                 return;
    166.          
    167.             //Store RaycastHits.
    168.             for (var i = 0; i < groundHits.Length; i++)
    169.                 groundHits[i] = new RaycastHit();
    170.  
    171.             //Set grounded. Now we know for sure that we're grounded.
    172.             grounded = true;
    173.         }
    174.          
    175.         protected override void FixedUpdate()
    176.         {
    177.             //Move.
    178.             MoveCharacter();
    179.          
    180.             //Unground.
    181.             grounded = false;
    182.         }
    183.  
    184.         /// Moves the camera to the character, processes jumping and plays sounds every frame.
    185.         protected override void Update()
    186.         {
    187.             //Get the equipped weapon!
    188.             equippedWeapon = playerCharacter.GetInventory().GetEquipped();
    189.          
    190.             //Play Sounds!
    191.             PlayFootstepSounds();
    192.  
    193.             if (Input.GetKeyDown(KeyCode.Space)) {
    194.                 Jump();
    195.             }
    196.  
    197.             if (Input.GetKeyDown(KeyCode.Z)) {
    198.                 Slide();
    199.             }
    200.  
    201.             if (speedRunning > speedRunningOriginal) {
    202.                 speedRunning -= Time.deltaTime * slideForce * slideForce * (slideForce / 1.2f);
    203.                 transform.GetChild(0).GetComponent<Animator>().SetBool("Running", false);
    204.              
    205.             }
    206.             else {
    207.                 sliding = false;
    208.             }
    209.  
    210.             if (speedRunning < speedRunningOriginal) {
    211.                 speedRunning = speedRunningOriginal;
    212.             }
    213.         }
    214.  
    215.         #endregion
    216.  
    217.         #region METHODS
    218.  
    219.         private void MoveCharacter()
    220.         {
    221.             #region Calculate Movement Velocity
    222.  
    223.             //Get Movement Input!
    224.             Vector2 frameInput = playerCharacter.GetInputMovement();
    225.             //Calculate local-space direction by using the player's input.
    226.             var movement = new Vector3(frameInput.x, 0.0f, frameInput.y);
    227.          
    228.             //Running speed calculation.
    229.             if(playerCharacter.IsRunning())
    230.                 movement *= speedRunning;
    231.             else if (playerCharacter.IsSprinting()) {
    232.                 movement *= speedSprinting;
    233.             }
    234.             else
    235.             {
    236.                 //Multiply by the normal walking speed.
    237.                 movement *= speedWalking;
    238.             }
    239.  
    240.             //World space velocity calculation. This allows us to add it to the rigidbody's velocity properly.
    241.             movement = transform.TransformDirection(movement);
    242.  
    243.             #endregion
    244.          
    245.             //Update Velocity.
    246.             Velocity = new Vector3(movement.x, Velocity.y, movement.z);
    247.         }
    248.  
    249.         /// <summary>
    250.         /// Plays Footstep Sounds. This code is slightly old, so may not be great, but it functions alright-y!
    251.         /// </summary>
    252.         private void PlayFootstepSounds()
    253.         {
    254.             //Check if we're moving on the ground. We don't need footsteps in the air.
    255.             if (grounded && rigidBody.velocity.sqrMagnitude > 0.1f)
    256.             {
    257.                 //Select the correct audio clip to play.
    258.                 audioSource.clip = playerCharacter.IsRunning() ? audioClipRunning : audioClipWalking;
    259.                 //Play it!
    260.                 if (!audioSource.isPlaying)
    261.                     audioSource.Play();
    262.             }
    263.             //Pause it if we're doing something like flying, or not moving!
    264.             else if (audioSource.isPlaying)
    265.                 audioSource.Pause();
    266.         }
    267.  
    268.         bool sliding = false;
    269.  
    270.         void Slide() {
    271.             if (sliding) return;
    272.  
    273.  
    274.             speedRunning *= slideForce;
    275.             transform.GetChild(0).GetComponent<Animator>().SetBool("Running", false);
    276.             transform.GetChild(0).GetComponent<Animator>().SetBool("Sprinting", false);
    277.  
    278.             sliding = true;
    279.         }
    280.  
    281.         [SerializeField] float jumpForce;
    282.  
    283.         void Jump() {
    284.  
    285.             if (!grounded) return;
    286.          
    287.             rigidBody.AddForce(transform.up * jumpForce);
    288.          
    289.         }
    290.      
    291.         #endregion
    292.     }
    293. }
     
  4. BKsingh2715

    BKsingh2715

    Joined:
    Sep 24, 2021
    Posts:
    17
    @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

    upload_2024-4-1_20-6-58.png

    this is the prefab

    upload_2024-4-1_20-7-58.png
     
  5. BKsingh2715

    BKsingh2715

    Joined:
    Sep 24, 2021
    Posts:
    17
    and i have the animator and some other scripts here

    upload_2024-4-1_20-10-21.png
     
  6. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,892
    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.
     
  7. BKsingh2715

    BKsingh2715

    Joined:
    Sep 24, 2021
    Posts:
    17
    @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!
     
  8. BKsingh2715

    BKsingh2715

    Joined:
    Sep 24, 2021
    Posts:
    17
    @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
     
  9. BKsingh2715

    BKsingh2715

    Joined:
    Sep 24, 2021
    Posts:
    17
    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!
     
    contact_unity103 likes this.