Search Unity

  1. We are migrating the Unity Forums to Unity Discussions by the end of July. Read our announcement for more information and let us know if you have any questions.
    Dismiss Notice
  2. Dismiss Notice

Question Why would just the client not update on the host's side?

Discussion in 'Netcode for GameObjects' started by gamecreatorc1, Mar 30, 2024.

  1. gamecreatorc1

    gamecreatorc1

    Joined:
    Dec 12, 2019
    Posts:
    65
    Using Unity 2022.3.19.f1, Netcode 1.7.1. Testing using ParrelSync on the same computer.

    I have 1 player character prefab loaded in for the host and a separate prefab for the client (using SpawnWithOwnership for both). They're both rigid body and they both run fine on their own computers. In addition, the client also sees the host running around properly. However, the client never moves in the host's game.

    I've made sure they all have Network Rigidbody components and their Network Transform syncing have all movement checked on all prefabs. What could be causing this?

    Just now I also tried loading the same single prefab for both players and the issue remains.
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    7,004
    Without seeing any of your code and prefab's setup, and possibly errors/warnings in the console (if any), we simply cannot begin to guess what might be wrong. ;)

    Keep in mind that the NetworkRigidbody still requires a NetworkTransform to sync position.

    And generally: rigidbody-controlled players are awkward in singleplayer already, over the network this will feel sluggish, like walking through molasses. Unless you are prepared to handle these complexities or have a very special game where this sort of movement would work to its advantage, it's best to stick to kinematic character controllers.
     
  3. gamecreatorc1

    gamecreatorc1

    Joined:
    Dec 12, 2019
    Posts:
    65
    Thank you. I started to simplify things by having the Netcode spawn the players and only spawning that 1 prefab for both players but the issue persists. Still researching and will add details if I can't figure it out.
     
    Last edited: Mar 30, 2024
  4. gamecreatorc1

    gamecreatorc1

    Joined:
    Dec 12, 2019
    Posts:
    65
    I really wish documentation was a bit more thorough. When are you supposed to and not supposed to use DefaultNetworkPrefabs? Is DefaultNetworkPrefabs supposed to be the same as NetworkPrefabsList?

    DefaultNetworkPrefabs.png
     
  5. gamecreatorc1

    gamecreatorc1

    Joined:
    Dec 12, 2019
    Posts:
    65
    Here are the code and prefab setups. There are no errors now. I'm trying to implement the free Kinematic Character Controller, which uses Rigid Body.

    Let me know if you'd like to see anything else.

    Code (CSharp):
    1. using KinematicCharacterController.Examples;
    2. using Unity.Netcode;
    3. using Unity.VisualScripting;
    4. using UnityEngine;
    5.  
    6. public class Player : NetworkBehaviour
    7. {
    8.     public override void OnNetworkSpawn()
    9.     {
    10.         base.OnNetworkSpawn();
    11.  
    12.         if(!IsOwner) enabled = false;
    13.         else
    14.         {
    15.             Debug.Log("We own " + name);
    16.  
    17.             //  Enable the two movement scripts on this player
    18.             Component scriptToEnable = GetComponent("ExampleCharacterController");
    19.             if(scriptToEnable != null) ((Behaviour)scriptToEnable).enabled = true;
    20.             else Debug.LogWarning($"Script '{"ExampleCharacterController"}' not found on this GameObject.");
    21.  
    22.             scriptToEnable = GetComponent("KinematicCharacterMotor");
    23.             if(scriptToEnable != null) ((Behaviour)scriptToEnable).enabled = true;
    24.             else Debug.LogWarning($"Script '{"KinematicCharacterMotor"}' not found on this GameObject.");
    25.  
    26.             // Find all GameObjects in the scene
    27.             GameObject[] allGameObjects = Resources.FindObjectsOfTypeAll<GameObject>();
    28.  
    29.             bool foundMyGO = false;
    30.  
    31.             // Iterate through all GameObjects
    32.             foreach(GameObject go in allGameObjects)
    33.             {
    34.                 if(go.name == "PlayerController")
    35.                 {
    36.                     // Set the GameObject named "PlayerController" to active
    37.                     go.SetActive(true);
    38.  
    39.                     go.GetComponent<ExamplePlayer>().Character = this.GetComponent<ExampleCharacterController>();
    40.  
    41.                     foundMyGO = true;
    42.                     break;
    43.                 }
    44.             }
    45.  
    46.         }
    47.     }
    48. }
    Network Manager:
    Assume the player prefab is dragged into the Network Manager. I took it out for further testing of different prefab spawning. The client doesn't move on the host either way.
    NetworkManager.png

    Player Prefab
    PlayerPrefab.png
     
  6. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    7,004
    DefaultNetworkPrefabs is simply the default, auto-generated NetworkPrefabsList asset that NGO creates in Assets/ just so one list exists that you can add prefabs to.

    It's a bit annoying because NGO keeps creating that default list even when you're using your own network prefabs list. You can alter the path to the default list in the project settings and make it match yours, but moving the asset or rename a folder in the path and you get that default list created again.

    :eek:

    I wasn't even aware that you can get components by string!
    Please don't do that. Use GetComponent<ExampleCharacterController>() to be type-safe. Getting or finding things by string is a flawed practice that will cause issues down the road.

    This does not do what your comment indicates! It will also return prefab GameObjects and internal objects! In any case a lot more than you need.

    You also don't need to get the game objects themselves when you can get the components directly. Use the appropriate variant of GetComponent(InChildren/InParent).

    Given the above, can you be sure there's only one game object named "PlayerController"?
    Again, string comparisons are terrible practice and should not be relied on. Especially when you instantiate prefabs, you'll notice their names actually becomes suffixed like "PlayerController (Clone)".

    I would not call SetActive on game objects in a network game when the target object has a NetworkObject on it (or in one of its children). This is likely going to cause issues because networked objects need to be in sync across the network for all clients. To show/hide game objects for individual clients the concept of NetworkObject visibility exists.
    But I assume this is just the input script? In that case this is okay.
     
    gamecreatorc1 likes this.
  7. gamecreatorc1

    gamecreatorc1

    Joined:
    Dec 12, 2019
    Posts:
    65
    Thank you for the tips and the warnings about using strings. While I don't think this addresses the problem, they are valuable nonetheless.