PlayerObjects and player prefabs
PlayerObjects are an optional feature in Netcode for GameObjects that you can use to assign a NetworkObject to a specific client. A client can only have one PlayerObject.
PlayerObjects are instantiated by reference to a player prefab, which defines the characteristics of the PlayerObject.
Defining defaults for player prefabs
If you're using UnityEngine.InputSystem.PlayerInput
or UnityEngine.PhysicsModule.CharacterController
components on your player prefab(s), you should disable them by default and only enable them for the local client's PlayerObject. Otherwise, you may get events from the most recently instantiated player prefab instance, even if it isn't the local client instance.
You can disable these components in the Inspector view on the prefab itself, or disable them during Awake
in one of your NetworkBehaviour
components. Then you can enable the components only on the owner's instance using code like the example below:
PlayerInput m_PlayerInput;
private void Awake()
{
m_PlayerInput = GetComponent<PlayerInput>();
m_PlayerInput.enabled = false;
}
public override void OnNetworkSpawn()
{
m_PlayerInput.enabled = IsOwner;
base.OnNetworkSpawn();
}
public override void OnNetworkDespawn()
{
m_PlayerInput.enabled = false;
base.OnNetworkDespawn();
}
Spawning PlayerObjects
Session-mode agnostic methods
Netcode for GameObjects can spawn a default PlayerObject for you. If you enable Create Player Prefab in the NetworkManager and assign a valid prefab, then Netcode for GameObjects spawns a unique instance of the designated player prefab for each connected and approved client, referred to as the PlayerObject.
To manually spawn an object as PlayerObject, use the following method:
GetComponent<NetworkObject>().SpawnAsPlayerObject(clientId);
If the player already had a prefab instance assigned, then the client owns the NetworkObject of that prefab instance unless there's additional server-side specific user code that removes or changes the ownership.
Alternatively, you can choose not to spawn anything immediately after a client connects and instead use a NetworkBehaviour component to handle avatar/initial player prefab selection. This NetworkBehaviour component could be configured by the server or initiating session owner, or be associated with an in-scene or dynamically spawned NetworkObject, as suits the needs of your project.
Client-server contexts only
In addition to the session-mode agnostic spawning methods above, you can assign a unique player prefab on a per-client connection basis using a client connection approval process when in client-server contexts.
Distributed authority contexts only
In addition to the session-mode agnostic spawning methods above, you can use the OnFetchLocalPlayerPrefabToSpawn
method to assign a unique player prefab on a per-client basis when in distributed authority contexts.
To use OnFetchLocalPlayerPrefabToSpawn
in your project, assign a callback handler to OnFetchLocalPlayerPrefabToSpawn
and whatever the client script returns is what will be spawned for that client. Ensure that the prefab being spawned is in a NetworkPrefabList registered with the NetworkManager.
If you don't assign a callback handler to OnFetchLocalPlayerPrefabToSpawn
, then the default behaviour is to return the NetworkConfig.PlayerPrefab
(or null if neither are set).
AutoSpawnPlayerPrefabClientSide
requiredFor OnFetchLocalPlayerPrefabToSpawn
to work, AutoSpawnPlayerPrefabClientSide
must be enabled.
PlayerObject spawning timeline
When using automatic methods of PlayerObject spawning (such as enabling Create Player Prefab in the NetworkManager), PlayerObjects are spawned at different times depending on whether you have scene management enabled.
- When scene management is disabled, PlayerObjects are spawned when a joining client's connection is approved.
- When scene management is enabled, PlayerObjects are spawned when a joining client finishes initial synchronization.
If you choose not to automatically spawn a PlayerObject when a client joins, then the timing of when a PlayerObject is spawned is up to you based on your own implemented code.
Finding PlayerObjects
To find a PlayerObject for a specific client ID, you can use the following methods:
Within a NetworkBehaviour, you can check the local NetworkManager.LocalClient
to get the local PlayerObjects:
NetworkManager.LocalClient.PlayerObject
Conversely, on the server-side, if you need to get the PlayerObject instance for a specific client, you can use the following:
NetworkManager.Singleton.ConnectedClients[clientId].PlayerObject;
To find your own player object just pass NetworkManager.Singleton.LocalClientId
as the clientId
in the sample above.