Skip to content

Tags

Tags are zero-cost markers that classify entities. They carry no data — they categorize entities for templates, systems, and queries.

Defining tags

Tags are empty structs implementing ITag:

public static class GameTags
{
    public struct Player : ITag { }
    public struct Enemy : ITag { }
    public struct Bullet : ITag { }
}

Tags on templates

Tags are declared via ITagged:

public partial class SpinnerEntity : ITemplate, ITagged<SampleTags.Spinner>
{
    Rotation Rotation;
}

See Templates.

Tags in systems

Systems target tag combinations to iterate only matching entities:

[ForEachEntity(typeof(SampleTags.Spinner))]
void Execute(ref Rotation rotation) { /* ... */ }

[ForEachEntity(typeof(BallTags.Ball), typeof(BallTags.Active))]
void Execute(in ActiveBall ball) { /* ... */ }

Tags also drive manual iteration. World.Query() and aspect queries both accept tag filters:

// Aspect query — bundled component access through the aspect's properties.
foreach (var player in PlayerView.Query(World).WithTags<GameTags.Player>())
{
    player.Position += player.Velocity * World.DeltaTime;
}

// World.Query().SingleHandle() — returns an EntityHandle; useful when no aspect fits.
EntityHandle boss = World.Query().WithTags<GameTags.Boss>().SingleHandle();

See Queries & Iteration for the full filter / terminator API.

Storage

Entities with the same tag combination are stored together in contiguous memory for cache-friendly iteration.

For the storage model and the low-level TagSet / GroupIndex / Tag<T> APIs, see Groups, GroupIndex & TagSets.