Process the standard Ultimate Character Controller scene first, then run the PUN scene setup to add the services that spawn players, synchronize state, identify scene colliders, and map item types.
Run scene setup
- Complete the standard Scene Setup workflow, including its camera setup.
- Open Tools > Opsive > Ultimate Character Controller > Add-Ons Manager > PUN Multiplayer.
- Enable Add Scene Identifiers if melee hits or other messages must identify colliders that are part of the scene.
- Select Setup Scene, then save the scene.

The manager creates a PunGame GameObject containing:
PunObjectPool, which creates and synchronizes pooled network objects.SpawnManager, which selects and instantiates the player character when a client joins a room.PunStateManager, which sends current state information to a joining client.StateManager.SendStateChangeEventmust be enabled for this synchronization.ItemTypeTracker, which maps item type IDs to item types on every client.
When Add Scene Identifiers is enabled, setup adds PunObjectIdentifier to scene colliders without requiring a Photon View on each static object. Rerun scene setup after adding or replacing colliders, then save the scene so the identifiers are retained.
Register spawnable prefabs
Add every network-spawned projectile, grenade, pickup, and similar prefab to PunObjectPool > Spawnable Prefabs. Local-only decals, particles, and effects do not need to be registered unless their creation or state must be replicated.

An "Unable to spawn" error identifies a prefab missing from this list or a different prefab reference from the one that was registered.
Configure item tracking
Assign the project’s Item Collection to ItemTypeTracker. It loads the item type mapping when the room starts so every client interprets synchronized item IDs consistently.
Configure character spawning
The default SingleCharacterSpawnManager always spawns the prefab assigned to Character. To select a prefab from player or match data, derive from SpawnManagerBase and override GetCharacterPrefab:
using UnityEngine;
using Opsive.UltimateCharacterController.AddOns.Multiplayer.PhotonPun.Game;
using Photon.Realtime;
public class MySpawnManager : SpawnManagerBase
{
protected override GameObject GetCharacterPrefab(Player newPlayer)
{
return null; // Replace with deterministic game-specific selection.
}
}
GetCharacterPrefab runs independently on every client. Base the result on player data shared identically by all clients; a local random choice or unsynchronized state can make different clients select different prefabs for the same player.
Verify with two clients
Create a room with one client and join it with another. Confirm that both clients see the same character prefab, pooled projectile, pickup state, and scene-object hit. Then change a synchronized state before a third client joins and confirm that PunStateManager supplies the current value to the late joiner.