Unity-Technologies / com.unity.netcode.gameobjects

Netcode for GameObjects is a high-level netcode SDK that provides networking capabilities to GameObject/MonoBehaviour workflows within Unity and sits on top of underlying transport layer.
MIT License
2.15k stars 435 forks source link

NetworkObjects spawned inside a scene are spawned before the scene is loaded on late-joining clients #3115

Open Moe-Baker opened 2 weeks ago

Moe-Baker commented 2 weeks ago

Description

NetworkObjects spawned inside a scene are spawned before the scene is loaded on late-joining clients using Distributed Authority.

Reproduce Steps

  1. Clients A & B enter matchmaking.
  2. Client A is assigned NetworkManager session owner and loads a scene "Scene".
  3. Scene contains a "Level" NetworkBehaviour script.
  4. Level script has an OnInSceneObjectsSpawned override and will spawn a "Player" NetworkObject on it.
  5. The Player is spawned via SpawnWithOwnership(NetworkManager.Singleton.LocalClientId, destroyWithScene: true).
  6. The Player has a NetworkBehaviour with an OnNetworkPostSpawn override and will register itself with the Level.
  7. All this works correctly for Client A.
  8. When a late-joining Client B tries to join, it will sometimes (random) spawn Client A's Player before it even Loads the Level's Scene.

Actual Outcome

A null reference exception as Client A's Player tries to register itself on the Level script before the Scene is even loaded.

Expected Outcome

That the logical flow of scene and object spawning is maintained. When a late-joining client joins the game, they should first load the active scene, and then spawn NetworkObjects, not just randomly do both.

Environment

NoelStephensUnity commented 2 weeks ago

@Moe-Baker

This part of your steps:

I need a bit more context as to why you want the in-scene placed NetworkObject to spawn the players? Is there any way you could provide me with a replication project (it will help me narrow down the issue faster)? If not, then I need some additional details behind using the in-scene placed NetworkObject as opposed to just using the client to handle the spawning...even just the script on the in-scene placed NetworkObject would help me understand the sequence better.

Moe-Baker commented 2 weeks ago

I need a bit more context as to why you want the in-scene placed NetworkObject to spawn the players

I find that this better organizes my project, we have a few different game modes, with a few different player prefabs, so choosing the player prefab inside the loaded scene is more convenient for me.

Is there any way you could provide me with a replication project

I'll create a replicated project and share it later.

even just the script on the in-scene placed NetworkObject would help me understand the sequence better

For the time being, these are the two scripts stripped down to the offending parts. Player Script & Level Script

NoelStephensUnity commented 1 week ago

@Moe-Baker

What I would recommend is to:

There is a known issue where the Multiplayer SDK "re-enables" the "Auto Spawn Player Prefab" setting when joining a distributed authority session, but a PR to remove that is in place and should be in the next update.

Until then, you can not assign a player prefab to avoid the initial automatic spawn and just rely on the MiniGamesLevel to handle this for you.

Let me know if this helps?