Making a player class selection system w/ Netcode.
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
public class PlayerPrefabManager : NetworkBehaviour
{
public static PlayerPrefabManager Instance { get; private set; }
[SerializeField] private GameObject marinePrefab;
[SerializeField] private GameObject ninjaPrefab;
[SerializeField] private GameObject zombiePrefab;
[SerializeField]
private LobbyManager.PlayerCharacter[] playerCharacters;
private Dictionary<LobbyManager.PlayerCharacter, GameObject> playerPrefabs;
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(this.gameObject);
}
else
{
Instance = this;
DontDestroyOnLoad(this.gameObject);
}
int maxPlayers = 10; // Replace with your game's actual maximum player count.
playerCharacters = new LobbyManager.PlayerCharacter[maxPlayers];
playerPrefabs = new Dictionary<LobbyManager.PlayerCharacter, GameObject>
{
{ LobbyManager.PlayerCharacter.Marine, marinePrefab },
{ LobbyManager.PlayerCharacter.Ninja, ninjaPrefab },
{ LobbyManager.PlayerCharacter.Zombie, zombiePrefab }
};
foreach (var prefab in playerPrefabs)
{
if (prefab.Value == null)
{
Debug.LogError($"{prefab.Key} prefab is not assigned in the inspector.");
}
}
}
public override void OnNetworkSpawn()
{
Debug.Log($"OnNetworkSpawn - OwnerClientId: {OwnerClientId}");
SpawnPlayerServerRpc();
}
[ServerRpc(RequireOwnership = false)]
void SpawnPlayerServerRpc(ServerRpcParams rpcParams = default)
{
// Get the ID of the client that sent the RPC
ulong senderClientId = rpcParams.Receive.SenderClientId;
Debug.Log($"SpawnPlayerServerRpc - clientId: {senderClientId}");
SpawnPlayerOnClients(senderClientId);
}
void SpawnPlayerOnClients(ulong clientId)
{
Debug.Log($"SpawnPlayerOnClients - clientId: {clientId}");
if (GetPlayerPrefab(playerCharacters[clientId]) == null)
{
Debug.LogError($"Prefab for character {playerCharacters[clientId]} is missing. Defaulting to Marine.");
playerCharacters[clientId] = LobbyManager.PlayerCharacter.Marine;
}
// Instantiate player object
Debug.Log("Spawning Player: " + playerCharacters[clientId]);
GameObject player = Instantiate(GetPlayerPrefab(playerCharacters[clientId]));
// Get the NetworkObject component
var playerNetworkObject = player.GetComponent<NetworkObject>();
// Spawn the player object on all clients
playerNetworkObject.SpawnAsPlayerObject(clientId);
}
public GameObject GetPlayerPrefab(LobbyManager.PlayerCharacter playerCharacter)
{
if (playerPrefabs.TryGetValue(playerCharacter, out GameObject prefab))
{
return prefab;
}
Debug.LogError($"No prefab found for player character: {playerCharacter}");
return null;
}
[ServerRpc(RequireOwnership = false)]
public void SetPlayerPrefabServerRPC(LobbyManager.PlayerCharacter playerCharacter_, ServerRpcParams rpcParams = default)
{
Debug.Log("Setting player character " + playerCharacter_ + " for clientId: " + rpcParams.Receive.SenderClientId);
playerCharacters[rpcParams.Receive.SenderClientId] = playerCharacter_;
Debug.Log("Player Character changed to: " + playerCharacters[rpcParams.Receive.SenderClientId]);
}
}
public void FinalizeSelectClass()
{
Debug.Log("Calling SetPlayerPrefabServerRPC");
PlayerPrefabManager.Instance.SetPlayerPrefabServerRPC(character);
}
public async void UpdatePlayerCharacter(PlayerCharacter playerCharacter)
{
FinalizeSelectClass();
if (joinedLobby != null)
{
try
{
UpdatePlayerOptions options = new UpdatePlayerOptions();
options.Data = new Dictionary<string, PlayerDataObject>() {
{
KEY_PLAYER_CHARACTER, new PlayerDataObject(
visibility: PlayerDataObject.VisibilityOptions.Public,
value: playerCharacter.ToString())
}
};
character = playerCharacter;
string playerId = AuthenticationService.Instance.PlayerId;
Lobby lobby = await LobbyService.Instance.UpdatePlayerAsync(joinedLobby.Id, playerId, options);
joinedLobby = lobby;
OnJoinedLobbyUpdate?.Invoke(this, new LobbyEventArgs { lobby = joinedLobby });
}
catch (LobbyServiceException e)
{
Debug.Log(e);
}
}
}
When I run this, FinalizeSelectClass() gets called, but SetPlayerPrefabServerRPC doesnt get called. There is no debug message, and all the player prefabs spawn the same, regardless of the chosen character.
(Sorry, I’m new to netcode.)