[NetCode] How to properly destroy entities?

tl;dr I add the NetworkStreamRequestDisconnect component and destroy the entity in the next frame, but this gives fleeting error messages. Are these errors cause for concern?

I have a barebones Unity project that includes the NetCode tutorial, with 1 extra component, and 2 extra systems.

  • The extra component just contains a “Health” integer attribute.
    HealthComponent.cs
using Unity.Entities;
using Unity.NetCode;

[GenerateAuthoringComponent]
public struct HealthComponent : IComponentData
{
    [GhostDefaultField]
    public int Health;
}
  • HealthSystem adds the NetworkStreamRequestDisconnect component to entities with health <= 0. HealthCleanupSystem runs before HealthSystem and destroys any entity with the NetworkStreamRequestDisconnect. This ensures that the entity is destroyed in the frame after the object is disconnected (or so I thought)
    HealthSystem.cs
using Unity.Entities;
using Unity.NetCode;

public class HealthSystem : ComponentSystem
{
    protected override void OnUpdate()
    {
        /**
         * Send disconnect request, according to NetCode documentation:
         * https://docs.unity3d.com/Packages/com.unity.netcode@0.0/manual/network-connection.html?q=destroy
         */
        Entities.ForEach((
            Entity entity,
            ref HealthComponent health) =>
        {
            if (health.Health <= 0)
            {
                EntityManager.AddComponent<NetworkStreamRequestDisconnect>(entity);
            }
        });
    }
}

[UpdateBefore(typeof(HealthSystem))]
public class HealthCleanupSystem : ComponentSystem
{
    protected override void OnUpdate()
    {
        /**
         * Remove disconnected objects.
         */
        Entities.WithAll<NetworkStreamRequestDisconnect>().ForEach((
            Entity entity,
            ref HealthComponent health) =>
        {
            PostUpdateCommands.DestroyEntity(entity);
        });
    }
}

However, once entities reach health <= 0, I see the following 3 errors in my console, exactly once per entity destroyed:

With that said, the code works, and no more errors are thrown. Just wondering: is this is a transient issue? Am I not destroying entities correctly in the networked setting?

I found threads on despawning that seemed to not be related. This thread mentions disconnect detection but doesn’t appear to have a solution. I found NetworkStreamRequestDisconnect on the official netcode docs.

I suspect the error is caused by deleting the ghost on the client without receiving a despawn from the server. You have to make sure that your despawn systems are server only or you will get errors. In your sample code you should add [UpdateInGroup(typeof(ServerSimulationSystemGroup))] to the HealthSystem and HealthCleanupSystem.

NetworkStreamRequestDisconnect is for disconnecting a connected client, it is not for despawning an entity. You can just destroy the entity using an EntityCommandBuffer on the server without any destroy tags, but if you do want to use one you should probably create your own instead of using the Disconnect tag.

1 Like

Ahh that makes a lot of sense… looks like I was inadvertently managing game logic client-side. Just beginning to understand how the Asteroids sample offloads game logic to server (the sample is super helpful by the way, thanks).

Whoops, gotcha.

Really appreciate the reply! This clears my confusion (I ran into more serious errors when I tried delete the player object. What you said above now explains why, oops.)