Skip to content


Entities (and their Ids) are recycled by an internal structure that resembles a Sparse Set.

To this end, Identities track a generation number that is incremented when the Entity's lifetime ends. This means their Ids are always unique, but not necessarily sequential. To the user, this is kept relatively opaque, as Identities are value types.

You can rely on the Entity's Id to be unique, and whether or not this specific Entity exists in a world is exposed through the Alive property.


Entities are considered Alive if they are spawned in a World. Entities that are despawned are considered dead. Their debug string shows this, too (see the output).

var entity = world.Spawn();
if (entity.Alive) Console.WriteLine(entity);
if (!entity.Alive) Console.WriteLine(entity);
E-00000001:00001 <fennecs.Identity>
E-00000001:00001 -DEAD-

Deferred Despawn

When despawned inside a Runner, operations are deferred until the end of the scope (or until the last World lock is released). An entity will be considered Alive until the World goes through WorldMode.Catchup to integrate these structural changes.

When despawning while iterating a Stream<> or Query directly, the Entity will immediately despawn and the enumerator will be invalidated. Take out a world lock if you want to keep iterating.

var worldLock = world.Lock();
foreach (var entity in world) // world is a query
    if (Random.Shared.NextSingle() >= 0.5f) entity.Despawn();
    if (entity.Alive) Console.WriteLine("Dead Fox Walking!");
worldLock.Dispose(); // this will catch up the despawns

Future Features

We're working on a way to make pending spawns and despawns apparent, as well.

fennecs is released under the MIT License. Neofox is released under the CC BY-NC-SA 4.0 License.