"The ghost collection contains a ghost which does not have a valid prefab on the client!"

I’m experiencing the following error in Unity 6.0, when I join a hosted game (the hosting instance of the game is just fine) when loading the game scene from another menu scene:

The ghost collection contains a ghost which does not have a valid prefab on the client! Ghost: ‘’ (‘ENTITY_NOT_FOUND’).

My game scene is dead simple:

‘GameSetup’ is the Authoring part of the FPS character controller netcode tutorial.

When using the automatic ClientServerBootstrap, and when hosting a game (Client + Server Worlds running in one game instance), the character and player entities spawn and I can move around the game world successfully, both in editor and in a build.

But when I arrive into the game scene from my Main Menu scene, as a client, I get those Ghost Collection errors:

I’m guessing that the two entities not found are the FirstPersonCharacter and FirstPersonPlayer entities the authoring script ought to handle. I guess that because those are the only two entities in the game, I don’t think it can be anything else.

Why is it failing on the client? Why does the Ghost Collection not have valid prefabs when coming in from the other scene?

My scripts for joining/hosting the game are also straight from the Entities For Netcode tutorial:

    // In both HostGame and JoinGame address is an endpoint like "192.168.1.1"
public static void HostGame(string address) {
	DestroyLocalSimulationWorld();
	var server = FrontendBootstrap.CreateServerWorld("ServerWorld");
	var client = FrontendBootstrap.CreateClientWorld("ClientWorld");
	
	if (World.DefaultGameObjectInjectionWorld == null)
		World.DefaultGameObjectInjectionWorld = server;
	SceneManager.LoadSceneAsync("Alt", LoadSceneMode.Single);

	NetworkEndpoint.TryParse(address, 13131, out NetworkEndpoint e);
	
	{
		using var query = server.EntityManager.CreateEntityQuery(ComponentType.ReadWrite<NetworkStreamDriver>());
		query.GetSingletonRW<NetworkStreamDriver>().ValueRW.Listen(e);
	}

	{
		using var query = client.EntityManager.CreateEntityQuery(ComponentType.ReadWrite<NetworkStreamDriver>());
		query.GetSingletonRW<NetworkStreamDriver>().ValueRW.Connect(client.EntityManager, e);
	}

}

public static void JoinGame(string address) {
	DestroyLocalSimulationWorld();
	var client = FrontendBootstrap.CreateClientWorld("ClientWorld");
	if (World.DefaultGameObjectInjectionWorld == null)
		World.DefaultGameObjectInjectionWorld = client;
	
	SceneManager.LoadSceneAsync("Alt", LoadSceneMode.Single);

	NetworkEndpoint.TryParse(address, 13131, out NetworkEndpoint e);
	{
		using var query = client.EntityManager.CreateEntityQuery(ComponentType.ReadWrite<NetworkStreamDriver>());
		query.GetSingletonRW<NetworkStreamDriver>().ValueRW.Connect(client.EntityManager, e);
	}
}

Nothing exotic there, I’m sure you’ll agree.

What’s going on here?

1 Like

I have the same behaviour but only on the Virtual Player with Multiplayer Play Mode

I took some time today to submit a bug report:

IN-90033

It contains a stripped-down project that clearly shows the error, reproduced.

Could one of the Netcode For Entities team please take a look?

The issue occurs because you are making on the server the game client “In Game” immediately after you receive the connection but on the client side, the sub-scene hasn’t been loaded and processed yet by the GhostCollectionSystem.

The server send to the client initially a list of “prefab ghost” that should be loaded and that the client needs to ack.

Normally, for simple case scenarios the client load the same sub-scene the server does before it receives the first snapshot, so the same prefabs are already present and processed at that point and the GhostCollectionSystem is able to assign to the GhostCollectionPrefab the right mapping.

But in case the server will set the connection to be in Game and the client load the scene later on, and meanwhile he receive the first snapshot, some actions need to be taken.?

It is rensposibility of the devs to check of any newly and pending assignment in the GhostCollectionPrefab list (any ghost that has the prefab field set to null or not existing) and mark these entry by setting the Loading state to LoadingState.Active.

This should be done each frame, until the resource (prefab) has been loaded and therefore the mapping assigned.