I’m starting to learn Unity’s Netcode for online multiplayer games.
I have a simple 2D scene where players can connect and control their own square. That works fine and everything gets synched between them.
I want to spawn monsters that get controlled by the server. Now, I get stuck commanding the monsters to walk to the nearest player.
My idea:
- Make sure only the server controls the monster (in OnNetworkSpawn)
- Let the server search for the nearest player (in RecalculateNearestPlayerServerRpc)
- Move the monster toward the nearest player (in Update)
My problem is that while trying to get all PlayerObjects the respective variables in the ConnectedClientsListof the NetworkManager is null:
NetworkManager.Singleton.ConnectedClientsList[0]
{Unity.Netcode.NetworkClient}
ClientId: 0
OwnedObjects: Count = 0
PlayerObject: null
NetworkManager.Singleton.ConnectedClientsList[1]
{Unity.Netcode.NetworkClient}
ClientId: 1
OwnedObjects: Count = 0
PlayerObject: null
Here is the code for my MonsterController:
public class MonsterController : NetworkBehaviour
{
private Rigidbody2D rb;
private float speed = 10.0f;
void Awake()
{
rb = GetComponent<Rigidbody2D>();
}
public override void OnNetworkSpawn()
{
if (!IsServer) enabled = false;
}
void Update()
{
RecalculateNearestPlayerServerRpc();
var dir = nearestPlayer.transform.position - transform.position;
rb.velocity = dir * speed;
}
[ServerRpc]
private void RecalculateNearestPlayerServerRpc()
{
float nearestPlayerDistance = float.MaxValue;
foreach (NetworkClient client in NetworkManager.Singleton.ConnectedClientsList)
{
float sqrDistance = (client.PlayerObject.transform.position-transform.position).sqrMagnitude;
if (sqrDistance < nearestPlayerDistance)
{
nearestPlayerDistance = sqrDistance;
nearestPlayer = client.PlayerObject;
}
}
}
}
I spawn and give ownership like this:
public class GameManager : NetworkBehaviour {
[SerializeField] private PlayerController _playerPrefab;
public override void OnNetworkSpawn() {
SpawnPlayerServerRpc(NetworkManager.Singleton.LocalClientId);
}
[ServerRpc(RequireOwnership = false)]
private void SpawnPlayerServerRpc(ulong playerId) {
var spawn = Instantiate(_playerPrefab);
spawn.NetworkObject.SpawnWithOwnership(playerId);
}
public override void OnDestroy() {
base.OnDestroy();
MatchmakingService.LeaveLobby();
if(NetworkManager.Singleton != null )NetworkManager.Singleton.Shutdown();
}
}
What am I doing wrong?