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.
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.
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.
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?
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.
using KinematicCharacterController.Examples;
using Unity.Netcode;
using Unity.VisualScripting;
using UnityEngine;
public class Player : NetworkBehaviour
{
public override void OnNetworkSpawn()
{
base.OnNetworkSpawn();
if(!IsOwner) enabled = false;
else
{
Debug.Log("We own " + name);
// Enable the two movement scripts on this player
Component scriptToEnable = GetComponent("ExampleCharacterController");
if(scriptToEnable != null) ((Behaviour)scriptToEnable).enabled = true;
else Debug.LogWarning($"Script '{"ExampleCharacterController"}' not found on this GameObject.");
scriptToEnable = GetComponent("KinematicCharacterMotor");
if(scriptToEnable != null) ((Behaviour)scriptToEnable).enabled = true;
else Debug.LogWarning($"Script '{"KinematicCharacterMotor"}' not found on this GameObject.");
// Find all GameObjects in the scene
GameObject[] allGameObjects = Resources.FindObjectsOfTypeAll<GameObject>();
bool foundMyGO = false;
// Iterate through all GameObjects
foreach(GameObject go in allGameObjects)
{
if(go.name == "PlayerController")
{
// Set the GameObject named "PlayerController" to active
go.SetActive(true);
go.GetComponent<ExamplePlayer>().Character = this.GetComponent<ExampleCharacterController>();
foundMyGO = true;
break;
}
}
}
}
}
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.
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.
I wasn’t even aware that you can get components by string!
Please don’t do that. Use GetComponent() to be type-safe. Getting or finding things by string is a flawed practice that will cause issues down the road.
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.