Skip to content
Archevolt
Esc
↑↓navigate↵open⌘Jpreview

Headless archetype ECS · MIT

The archetype ECS
for high performance .NET

Write components as structs and systems as plain C# methods. A source generator turns them into typed queries and schedules, and the runtime keeps every component in dense native tables.

Read the quickstart
dotnet add package Archevolt
Dependencies
0
Allocations
0 B
Optimized
AOT

Allocated per warmed update.

  • Zero allocations per warmed update
  • Source generated queries
  • Structure of arrays storage
  • NativeAOT and trimming
  • Bounded parallel execution
  • Change tracking
  • No package dependencies
  • MIT licensed
01The system

Two structs and a method. That is the whole system.

Components are unmanaged structs. A system is a static method that asks for ref to write and in to read. The generated loop calls Motion.Move directly for every entity that has both components.

  • Typed accessconcrete rows, nothing boxed or looked up by type
  • Compile timequeries, bundles, modules, and schedules are generated
  • Your codegenerated declarations stay in your namespace and partial types
Motion.csgenerated loop · per entity
[Component]
public readonly record struct Position(float X);

[Component]
public readonly record struct Velocity(float X);

public static partial class Motion
{
    [Each]
    public static void Move(scoped ref Position position, scoped in Velocity velocity)
    {
        position = position with { X = position.X + velocity.X };
    }
}

Runs under

JIT/Trimmed/NativeAOT

The same package, verified in clean consumers on each.

02What you get

Everything a frame needs, generated at compile time

Queries

Typed rows, no lookups

Named queries produce concrete rows with ref and ref readonly access. Nothing is boxed or looked up by type at run time.

Queries guide
Storage

Dense native tables

Components live in aligned, structure of arrays tables, one per archetype, outside the managed heap.

Architecture
Schedules

Ordering you declare once

Order systems with Order, Before, After, stages, and sets. The planner adds conservative ordering where access conflicts.

Schedules guide
Execution

Parallel when you ask for it

Serial execution is the reference behavior. Enable a bounded worker pool and mark eligible systems as partitioned.

Execution guide
Data flow

Changes, resources, messages

Track added and changed components, share resources, and send messages that each reader consumes at its own pace.

Messages guide
Deployment

Ready for NativeAOT

The package runs under JIT, trimming, and NativeAOT. The runtime has no package dependencies.

Installation
Guides

11 guides, one per feature

Components, modules, queries, schedules, resources, commands, and the rest, each with runnable code.

Explore the docs
03How it works

From package to running world in three steps

  1. Add the package

    One package holds the runtime and its source generator. Generated declarations stay in your namespace and your partial types.

    dotnet add package Archevolt
  2. Collect systems into a module

    A module gathers systems and bundles. A schedule declares which systems run and in what order.

    [Bundle]
    public readonly partial record struct Particle(Position Position, Velocity Velocity);
    
    [EcsModule, IncludeSystems(typeof(Motion)), IncludeBundle<Particle>]
    public static partial class GameEcs;
    
    [Schedule, Run(typeof(Motion), nameof(Motion.Move), Order = 0)]
    public sealed partial class Simulation;
  3. Build a world and run it

    Spawn entities from bundles, bind the schedule to the world, and run it once per update.

    using var world = new WorldBuilder().AddModule(GameEcs.Module).Build();
    var entity = world.Spawn(new Particle(new Position(0), new Velocity(1)));
    
    using var simulation = Simulation.Create(world);
    simulation.Run();
    
    Console.WriteLine(world.Get<Position>(entity).X); // 1

The quickstart puts these pieces together into one program that prints 1.

04Performance

Generated loops that keep pace with handwritten ones

0 B

managed allocations per warmed update, with one worker or four

for a Changed<T> scan with nothing changed, at 1,000 or 100,000 entities
0.16 µs
package dependencies in the runtime
0

Moving 100,000 entities, median µs per updateArchevolt's times include schedule dispatch, resource access, lease checks, and query traversal.

CaseMedian µsns per entity
Handwritten loopbaseline, no scheduler83.060.831
Generated [Each]94.630.946
Generated [EachBlock], indexed loop83.060.831
Named query, foreach over rows83.160.832
Generated [EachBlock], Vector25620.960.210

Medians of three process runs on an AMD Ryzen 9 5950X, Windows 11, Release build, 2 November 2026. The numbers come from one machine. They are not a regression limit or a ranking. Read the full performance report

05Sample

Every ship, rock, bullet, and particle is an entity

Archeoids is a playable Asteroids style game. Archevolt runs the gameplay, and Silk.NET handles the window, input, and rendering. Read it for spawn bundles, deferred commands, independent message readers, and invulnerability tags working together.

dotnet run --project samples/Archeoids -c Release
Play Archeoids in your browserExplore the Archeoids sample
Archeoids gameplay with a cyan ship, drifting asteroids, and a score and lives HUD.
06FAQ

Questions before you start

01Is Archevolt a game engine?

No. It is a headless ECS with no window, input, rendering, or audio. Pair it with a library such as Silk.NET, the way the Archeoids sample does, or use it to drive simulations without any graphics.

02What do I need to install?

One package, Archevolt, which contains the runtime and the Roslyn source generator. The runtime depends only on the .NET base library. The installation guide lists the SDK and language version it targets.

03Does it allocate during an update?

Measured warmed, fixed capacity updates allocate zero managed bytes, with one worker or four. Spawning and other structural changes can grow storage and allocate.

04Does it run systems in parallel?

Only when you opt in. Call UseParallelExecution(maxConcurrency: 4) on WorldBuilder and mark eligible systems with [Each(Partitioned = true)]. Small workloads can cost more to dispatch in parallel than to run serially, so measure first.

05Does it work with NativeAOT and trimming?

Yes. The package is verified in clean consumers under JIT, trimming, and NativeAOT.

06What does the generator change in my code?

It adds members to your declarations, so the types it touches must be partial. Generated code stays in the namespace and partial owner of the original declaration.

07How do systems add or remove components?

Structural changes inside systems go through Commands and become visible at schedule barriers. Outside a schedule, mutate the world directly on its owner thread.

08How does it compare to other ECS libraries?

The benchmark suite records Bevy reference measurements beside its own, but the numbers come from one machine and are not a ranking. The performance page lists every case and what it measures.

09Is it free to use?

Yes. Archevolt is open source under the MIT license, and the source is on GitHub.

Get started

Run your first system

Two structs, one method, and a schedule. The quickstart walks through the whole program.

Read the quickstart
dotnet add package Archevolt