Destroying Ghost Prefabs

I have been using GhostPrefabCreation.ConvertToGhostPrefab to turn some dynamically loaded addressable prefabs into ghost prefabs at runtime (I sync this dynamic list of prefabs to all Clients) but I have hit a bit of an issue when I need to restart the game level and flush all of the now unused ghost prefabs. Is there an easy way to do this because I unfortunately can’t just delete the ghost prefab outright. Multiple things start throwing errors about missing Entity references and checking the hierarchy there are many Unity handled buffers that will show missing Entity references (the Ghost Collection Prefab buffer and Code Ghost Prefab buffer for example).

So is there a way to delete ghost prefabs that were created at runtime?

Good question - I don’t believe there is (apart from reconnecting to the server). You can see what we do to fully clear the GhostCollection upon disconnect at about GhostCollectionSystem.cs:303 (though this may not be the full picture):

            if (m_InGameQuery.IsEmptyIgnoreFilter)
            {
                if (SystemAPI.GetSingletonRW<GhostCollection>().ValueRO.IsInGame)
                {
                    state.EntityManager.GetBuffer<GhostCollectionPrefab>(m_CollectionSingleton).Clear();
                    state.EntityManager.GetBuffer<GhostCollectionPrefabSerializer>(m_CollectionSingleton).Clear();
                    state.EntityManager.GetBuffer<GhostCollectionComponentIndex>(m_CollectionSingleton).Clear();
                    state.EntityManager.GetBuffer<GhostCollectionComponentType>(m_CollectionSingleton).Clear();
                    state.EntityManager.RemoveComponent<GhostPrefabTracking>(m_RegisteredGhostTypesQuery);
                    m_PendingAssignment.Clear();
                    for (int i = 0; i < m_AllComponentTypes.Length; ++i)
                    {
                        var ctype = m_AllComponentTypes[i];
                        ctype.UsedIndex = -1;
                        m_AllComponentTypes[i] = ctype;
                    }
                    m_GhostTypeToGhostCollectionPrefab.Clear();
                    m_GhostPrefabForGhostType.Clear();
#if UNITY_EDITOR || NETCODE_DEBUG
                    m_PendingNameAssignments.Clear();
                    m_PredictionErrorNames.Clear();
                    m_GhostNames.Clear();
                    m_currentPredictionErrorNamesCount = 0;
                    m_currentPredictionErrorCount = 0;
                    if (m_PrevPredictionErrorNamesCount > 0 || m_PrevGhostNamesCount > 0)
                    {
                        SystemAPI.GetSingletonRW<GhostStatsCollectionData>().ValueRW.SetGhostNames(state.WorldUnmanaged.Name, m_GhostNames, m_PredictionErrorNames);
                        if (SystemAPI.TryGetSingletonBuffer<GhostNames>(out var ghosts))
                            UpdateGhostNames(ghosts, m_GhostNames);
                        if (SystemAPI.TryGetSingletonBuffer<PredictionErrorNames>(out var predictionErrors))
                            UpdatePredictionErrorNames(predictionErrors, m_PredictionErrorNames);
                        m_PrevPredictionErrorNamesCount = 0;
                        m_PrevGhostNamesCount = 0;
                    }
#endif
                    var ghostCollection = SystemAPI.GetSingletonRW<GhostCollection>();
                    ghostCollection.ValueRW.IsInGame = false;
                    ghostCollection.ValueRW.NumLoadedPrefabs = 0;
#if UNITY_EDITOR || NETCODE_DEBUG
                    ghostCollection.ValueRW.NumPredictionErrors = 0;
#endif
                }
                return;
            }

In the short term, I’d recommend having the client reconnect to the server.

You can technically create and destroy prefabs at will but for clearing stuff out you must remove the NetworkStreamInGame from the connection.

there is no need to disconnect from the server at all. When you want to reload the level:

  • Remove the NetworkStreamInGame (ideally both client and server side for that connection)
  • Wait at least 2-3 frame on the client, 2 ticks on the server (because of command buffers you need a couple of frames),
  • Unload/Load the sub-scene (if necessary)
  • Re add the NetworkStreamInGame.
1 Like