Quickstart (Basic)
Docs / Getting started / Quickstart (Basic)
Get started with ZenECS in 5 minutes. This guide walks you through creating a world, adding components, and running systems.
Prerequisites
- Unity 2021.3+ or .NET Standard 2.1+
- ZenECS Core package installed
- Basic C# knowledge
Create World
A World is a container for entities, components, and systems. Create one via the Kernel:
using ZenECS.Core;
// Create kernel (manages multiple worlds)
var kernel = new Kernel();
// Create a world
var world = kernel.CreateWorld(null, "GameWorld");
In Unity, use EcsDriver:
using ZenECS.Adapter.Unity;
using ZenECS.Core;
// Kernel is automatically created by EcsDriver
var kernel = KernelLocator.Current;
var world = kernel.CreateWorld(null, "GameWorld", setAsCurrent: true);
Define Components
Components are pure data structures (structs):
public struct Position
{
public float X, Y;
public Position(float x, float y)
{
X = x;
Y = y;
}
}
public struct Velocity
{
public float X, Y;
public Velocity(float x, float y)
{
X = x;
Y = y;
}
}
Key Points:
- Components are
struct(value types) - No methods or behavior, just data
- Immutable by convention (readonly fields)
Create Entities and Add Components
Entities are unique IDs. Attach components to give them data:
// Create entity and add components using command buffer
using (var cmd = world.BeginWrite())
{
var entity = cmd.CreateEntity();
cmd.AddComponent(entity, new Position(0, 0));
cmd.AddComponent(entity, new Velocity(1, 0));
}
Using Command Buffer (recommended for structural changes):
using (var cmd = world.BeginWrite())
{
var entity = cmd.CreateEntity();
cmd.AddComponent(entity, new Position(0, 0));
cmd.AddComponent(entity, new Velocity(1, 0));
}
Write a System
Systems contain logic that processes entities:
using ZenECS.Core;
using ZenECS.Core.Systems;
[FixedGroup]
public sealed class MovementSystem : ISystem
{
public void Run(IWorld world, float deltaTime)
{
using var cmd = world.BeginWrite();
// Query entities with Position AND Velocity
foreach (var (entity, pos, vel) in world.Query<Position, Velocity>())
{
// Update position based on velocity
cmd.ReplaceComponent(entity, new Position(
pos.X + vel.X * deltaTime,
pos.Y + vel.Y * deltaTime
));
}
}
}
Key Points:
- Systems implement
ISystem - Use
[FixedGroup]for deterministic simulation - Query entities with
world.Query<T1, T2>() - Use command buffer for writes:
world.BeginWrite()
Register Systems
Add systems to the world:
world.AddSystems([new MovementSystem()]);
Systems run automatically during frame updates.
Run the Simulation
Drive the simulation with the kernel:
const float fixedDelta = 1f / 60f; // 60 FPS
while (running)
{
float dt = GetDeltaTime(); // Your delta time source
// Run simulation
kernel.PumpAndLateFrame(dt, fixedDelta, maxSubStepsPerFrame: 4);
}
In Unity, EcsDriver handles this automatically via Update() and FixedUpdate().
Complete Example
using ZenECS.Core;
using ZenECS.Core.Systems;
// 1. Create kernel and world
var kernel = new Kernel();
var world = kernel.CreateWorld(null, "GameWorld");
// 2. Define components
public struct Position { public float X, Y; }
public struct Velocity { public float X, Y; }
// 3. Create system
[FixedGroup]
public sealed class MovementSystem : ISystem
{
public void Run(IWorld world, float deltaTime)
{
using var cmd = world.BeginWrite();
foreach (var (entity, pos, vel) in world.Query<Position, Velocity>())
{
cmd.ReplaceComponent(entity, new Position(
pos.X + vel.X * deltaTime,
pos.Y + vel.Y * deltaTime
));
}
}
}
// 4. Register system
world.AddSystems([new MovementSystem()]);
// 5. Create entities
using (var cmd = world.BeginWrite())
{
var player = cmd.CreateEntity();
cmd.AddComponent(player, new Position(0, 0));
cmd.AddComponent(player, new Velocity(1, 0));
}
// 6. Game loop
const float fixedDelta = 1f / 60f;
while (running)
{
float dt = GetDeltaTime();
kernel.PumpAndLateFrame(dt, fixedDelta, maxSubStepsPerFrame: 4);
}
// 7. Cleanup
kernel.Dispose();
Reset/Dispose
Reset World
Clear all entities and components, keep systems:
world.Reset(); // Fast reset, keeps systems
Dispose
Clean up resources:
kernel.Dispose(); // Disposes all worlds
Next Steps
Now that you understand the basics:
- Explore Samples - See working examples
- Learn About Systems - Deep dive into system design
- Understand Queries - Advanced querying
- Try Unity Integration - Unity-specific features
Learning Path
Beginner:
- ✅ This guide (you're here!)
- What is ECS?
- Basic Sample
Intermediate:
Advanced:
Common Patterns
Query Pattern
Find entities with specific components:
foreach (var (entity, component) in world.Query<Component>())
{
// Process entity
}
Multiple Components
Query entities with multiple components:
foreach (var (entity, pos, vel, health) in world.Query<Position, Velocity, Health>())
{
// Entity has all three components
}
Read-Only Access
Read components without command buffer:
foreach (var (entity, pos) in world.Query<Position>())
{
var position = pos; // Read by value
// No writes needed
}
Troubleshooting
System Not Running
- Check system is registered:
world.AddSystems([new MySystem()]) - Verify system has
[FixedGroup]or[FrameGroup]attribute - Ensure world is being stepped:
kernel.PumpAndLateFrame(...)
Entities Not Found
- Verify entities have required components
- Check query matches component types
- Ensure entities are alive:
world.IsAlive(entity)
Components Not Updating
- Use command buffer for writes:
using var cmd = world.BeginWrite() - Replace components:
cmd.ReplaceComponent(...) - Check system is running and registered
See Also
- Installation Guide - How to install ZenECS
- World Guide - Deep dive into worlds
- Systems Guide - System design patterns
- Basic Sample - Complete working example