KeenEyes Roadmap
This document outlines the features needed to achieve parity with OrionECS, the TypeScript ECS framework that KeenEyes reimplements in C#.
Current Status
KeenEyes is well past parity scaffolding. The engine core (Phases 1-11), developer experience (Phases 12-14), production/performance work (Phases 16-17), and the deterministic replay system (Phase 18) are all substantially complete, along with the companion plugin ecosystem (Spatial, Physics, Persistence, Parallelism, Graphics, AI, Navigation, Localization, Network, Replay, Animation, Particles) and the KESL shader language (Phase 20) except for a small unchecked residue tracked below.
Recently landed (week of 2026-07-21): owner-authoritative sync, server reconciliation, lag compensation, and interest management (networking); IK solvers, look-at constraints, and root motion (animation); Particles Tier 1 (texture-sheet animation, emission shapes); tiled navmesh build, crowd simulation, off-mesh links, and tile streaming (navigation); snapshot state restoration, delta compression, ghost trails, and playtest session bundles (replay); and editor entity-scale benchmarks. A security/quality hardening pass (CodeQL alert remediation across src, editor, tests, samples, and tools) landed 2026-07-22/23.
The largest remaining gaps: Phase 19 (IDE Extension) has not been started; multi-world cross-world references and world cloning, cloud-save synchronization, and a concrete asset-import pipeline in the editor remain unbuilt. The desktop scene editor is under active development.
The foundational scaffolding remains in place:
Worldcontainer with isolated stateEntityasreadonly record structwith version trackingEntityBuilderwith fluentWith<T>()/WithTag<T>()APIIComponent/ITagComponentmarker interfacesComponentRegistrywith per-world component IDsQueryBuilderwithWith<>()/Without<>()filtersISystem/SystemBasewith Initialize/Update lifecycleSystemGroupfor grouped execution- Source generator attributes (
[Component],[System],[Query])
Phase 1: Core Completion (Foundation)
Essential features needed for basic usability.
1.1 Entity Operations
- [x]
World.Get<T>(entity)- retrieve component data - [x]
World.Set<T>(entity, value)- update component data - [x]
World.Add<T>(entity, component)- add component to existing entity - [x]
World.Remove<T>(entity)- remove component from entity - [x]
World.GetComponents(entity)- get all components on entity - [x]
World.Has<T>(entity)- check component presence - [x] Entity naming support (
World.Spawn(name),World.GetEntityByName(name))
1.2 Singletons / Resources
World-level data not tied to entities (time, input, config, etc.):
- [x]
World.SetSingleton<T>(value) - [x]
World.GetSingleton<T>() - [x]
World.TryGetSingleton<T>(out T value) - [x]
World.HasSingleton<T>() - [x]
World.RemoveSingleton<T>()
1.3 Command Buffer / Deferred Operations
Safe entity modification during iteration:
- [x]
CommandBufferclass - [x] Deferred entity creation (
CommandBuffer.Spawn()) - [x] Deferred component add/remove (
AddComponent,RemoveComponent,SetComponent) - [x] Deferred entity destruction (
CommandBuffer.Despawn()) - [x]
CommandBuffer.Flush(world)to execute buffered commands
Phase 2: Archetype Storage (Performance)
Replace dictionary-based storage with cache-friendly archetypes.
2.1 Archetype System
- [x]
Archetype- component type combination storage - [x]
ArchetypeChunk- contiguous component arrays with fixed-size chunks - [x] Archetype manager for efficient entity migrations
- [x]
ref Treturns for zero-copy component access
2.2 Object Pooling
- [x] Entity ID recycling (
EntityPool) - [x] Component array pooling (
ComponentArrayPool) - [x] Archetype chunk pooling (
ChunkPool) - [x] Memory usage statistics (
World.GetMemoryStats())
2.3 Query Caching
- [x]
QueryManagerfor cached queries - [x] Automatic cache invalidation on archetype changes
- [x] Query reuse across systems
Phase 3: Entity Hierarchy
Parent-child relationships for scene graphs and transforms.
- [x]
World.SetParent(child, parent) - [x]
World.GetParent(entity) - [x]
World.GetChildren(entity) - [x]
World.AddChild(parent, child) - [x]
World.RemoveChild(parent, child) - [x] Cascading despawn (destroy children with parent)
- [x] Hierarchy traversal utilities
Phase 4: Events & Change Tracking
Reactive patterns for responding to entity/component changes.
4.1 Event System
- [x]
World.OnComponentAdded<T>(handler) - [x]
World.OnComponentRemoved<T>(handler) - [x]
World.OnComponentChanged<T>(handler) - [x]
World.OnEntityCreated(handler) - [x]
World.OnEntityDestroyed(handler) - [x] General event bus for custom events
4.2 Change Tracking
- [x]
World.MarkDirty<T>(entity) - [x]
World.GetDirtyEntities<T>() - [x]
World.ClearDirtyFlags<T>() - [x] Automatic change detection option
- [x] Change tracking configuration
Phase 5: System Enhancements
Better control over system execution.
5.1 Lifecycle Hooks
- [x]
OnBeforeUpdate()- runs before entity processing - [x]
OnAfterUpdate()- runs after entity processing - [x]
OnEnabled()/OnDisabled()callbacks
5.2 Runtime Control
- [x]
system.Enabledproperty - [x]
World.EnableSystem<T>()/DisableSystem<T>() - [x]
World.GetSystem<T>()
5.3 Execution Order
- [x] Priority-based system sorting (Phase and Order parameters)
- [x]
[RunBefore(typeof(OtherSystem))]attribute - [x]
[RunAfter(typeof(OtherSystem))]attribute - [x] Topological sorting with cycle detection
- [x]
World.FixedUpdate()method for fixed timestep physics
Phase 6: Plugin System
Extensibility for physics, networking, rendering, etc.
6.1 Plugin Infrastructure
- [x]
IWorldPlugininterface - [x]
PluginContextfor registration - [x] Plugin metadata (name, version)
- [x]
Install()/Uninstall()lifecycle
6.2 WorldBuilder Pattern
- [x]
WorldBuilderclass - [x]
.WithPlugin<T>()fluent API - [x]
.WithFixedUpdateRate(fps)configuration - [x]
.WithDebugMode(enabled)configuration - [x]
.WithChangeTracking(mode)configuration
6.3 Runtime Plugin Management
- [x]
World.InstallPlugin(plugin) - [x]
World.UninstallPlugin(name) - [x]
World.HasPlugin(name) - [x]
World.GetPlugin<T>() - [x]
World.GetInstalledPlugins()
6.4 Extension API
- [x]
World.SetExtension<T>(api)- plugin-provided APIs - [x]
World.GetExtension<T>() - [x] Type-safe extension access
Phase 7: Inter-System Messaging
Decoupled communication between systems.
- [x]
MessageManager/IMessageBus - [x]
World.Send<T>(message) - [x]
World.Subscribe<T>(handler) - [x] Unsubscription via
IDisposable(EventSubscription) - [x] Typed message channels
- [x] Message queuing for deferred delivery (
QueueMessage,ProcessQueuedMessages)
Phase 8: Prefabs & Templates
Entity templates for content creation.
Note: The runtime prefab API below is being removed in favor of build-time
.keprefabsource generation (see issue #1079). Prefabs are now defined as.keprefabfiles and compiled into typed spawn methods by theSceneGenerator, rather than registered/spawned through the runtimePrefabManager.
- [x]
PrefabManager - [x]
World.RegisterPrefab(name, config) - [x]
World.SpawnFromPrefab(name) - [x]
World.SpawnFromPrefab(name, overrides) - [x] Prefab inheritance
- [x] Nested prefabs
Phase 9: Entity Tags (String-based)
Dynamic categorization beyond type-safe ITagComponent.
- [x]
World.AddTag(entity, tagName) - [x]
World.RemoveTag(entity, tagName) - [x]
World.HasTag(entity, tagName) - [x]
World.GetTags(entity) - [x] Query filtering by tags (
.WithTag("enemy")) - [x] Query exclusion by tags (
.WithoutTag("dead"))
Phase 10: Component Validation
Development-time safety checks.
- [x]
[RequiresComponent(typeof(T))]attribute - [x]
[ConflictsWith(typeof(T))]attribute - [x] Custom validation delegates
- [x] Validation toggle (dev vs production)
Phase 11: Serialization & Snapshots
Save/load world state.
- [x]
SnapshotManager - [x]
World.CreateSnapshot()- capture world state - [x]
World.RestoreSnapshot(snapshot)- restore state - [x] Entity serialization
- [x] Component serialization (opt-in via
[Component(Serializable = true)]) - [x] Binary and JSON format support
Phase 12: Logging System
Pluggable logging with multiple providers.
12.1 Log Provider Architecture
- [x]
ILogProviderinterface - [x]
LogManagerfor provider registration - [x] Multiple simultaneous providers
- [x] Provider-specific configuration
12.2 Built-in Providers
- [x] Console log provider (default)
- [x] File log provider
- [x] Debug output provider (IDE integration)
- [x] Null provider (disable logging)
12.3 Logging Features
- [x] Log levels (Trace, Debug, Info, Warning, Error, Fatal)
- [x] Log filtering by level and category
- [x] Structured logging with properties
- [x] Log scopes for context
- [x] Timestamp and source formatting
- [x] Performance-friendly (zero overhead when disabled)
12.4 ECS-Specific Logging
- [x] System execution logging
- [x] Entity lifecycle logging
- [x] Component change logging
- [x] Query execution logging
- [x] Configurable verbosity per category
Phase 13: Debugging & Profiling
Development tools and diagnostics.
13.1 Debug Mode
- [x]
World.DebugModetoggle (DebugController.IsDebugModewith events) - [x] Verbose logging option (
DebugOptions.OnDebugModeChangedcallback for logging integration) - [x] Entity/component inspection (
EntityInspectorwith full component details)
13.2 Profiling
- [x] System execution timing (
Profilerclass) - [x] Query performance metrics (
QueryProfilerclass) - [x] Memory usage tracking (
MemoryTrackerclass) - [x] GC allocation monitoring (
GCTrackerclass)
13.3 Visualization
- [x] Entity inspector API (
EntityInspector) - [x] System execution timeline (
TimelineRecorder) - [x] Archetype statistics (
MemoryTracker+IStatisticsCapability)
Phase 14: Testing Tools
Utilities for testing ECS code. Status: 75-80% Complete (KeenEyes.Testing package)
14.1 Test World Builder
- [x]
TestWorldBuilderwith fluent API - [x] Pre-configured test worlds
- [x] Isolated world instances per test
- [x] Deterministic entity ID generation
- [x] Time control (
TestClockfor manual tick advancement)
14.2 Assertion Helpers
- [x]
entity.ShouldHaveComponent<T>()(EntityAssertions) - [x]
entity.ShouldNotHaveComponent<T>()(EntityAssertions) - [x]
entity.ShouldBeAlive()/ShouldBeDead()(EntityAssertions) - [x]
component.ShouldEqual(expected)(ComponentAssertions) - [x]
world.ShouldHaveEntityCount(n)(WorldAssertions) - [ ]
query.ShouldMatchEntities(count)(partial - needs enhancement)
14.3 Mock Utilities
- [x] Mock system base class (
MockPlugin,MockPluginContext) - [x] System execution recording (
EventRecorder<T>) - [x] Component change tracking for tests (
EventRecorder) - [x] Event capture and verification (
EventAssertions)
14.4 Snapshot Testing
- [x] World state snapshots for comparison (
SnapshotComparer) - [x] Entity snapshot assertions (
SnapshotAssertions) - [x] Advanced component data diffing (
SnapshotComparerfield-levelFieldAdded/FieldRemoved/FieldChanged) - [x] Snapshot serialization format (uses Core's
SnapshotManager)
14.5 Test Fixtures
- [x] Common component fixtures (
CommonComponents- Position, Velocity, Health, etc.) - [x] Entity builder presets (
EntityPresets) - [x] System test harness (
SystemPresets) - [x] Integration test utilities (mock providers for Input, Graphics, Network, Logging)
Phase 15: Manager Architecture
Refactor World into specialized managers for better separation of concerns.
See ADR-001 for the full decision record.
Status: In Progress (Issue #82)
Current State
The World class has grown to 3,000+ lines with 10+ responsibilities, violating SRP.
Target Architecture
World (facade, ~300-400 lines)
├── HierarchyManager - Parent-child entity relationships
├── SystemManager - System registration, ordering, execution
├── PluginManager - Plugin lifecycle
├── SingletonManager - Global resource storage
├── ExtensionManager - Plugin-provided APIs
├── ArchetypeManager - (existing) Component storage
├── QueryManager - (existing) Query caching
└── ComponentRegistry - (existing) Component type registry
Extraction Order
- [x] Extract HierarchyManager (~676 lines)
- [x] Extract SystemManager (~365 lines)
- [x] Extract PluginManager (~169 lines)
- [x] Extract SingletonManager (~209 lines)
- [x] Extract ExtensionManager (~107 lines)
- [x] Reduce World to thin facade (~300-400 lines)
Constraints
- Managers are
internal(not public API) Worldremains the single entry point- Public API unchanged - no breaking changes
- Unit tests added for each manager before extraction
Phase 16: Production Readiness
Features for shipping production games.
16.1 Multi-World Support
- [x] Multiple independent worlds in one process
- [x] World isolation guarantees
- [ ] Cross-world entity references (optional)
- [ ] World templates/cloning
16.2 Component Schema Evolution
- [x] Component versioning
- [x] Migration handlers for schema changes
- [x] Backward compatibility utilities
- [x] Data upgrade pipelines
16.3 Enhanced Save/Load System
Beyond basic serialization:
- [x] Multiple save slots with metadata
- [x] Save slot management (create, delete, copy)
- [x] Compression (gzip, brotli)
- [x] Optional encryption (AES-256)
- [x] Checksum validation & corruption detection
- [ ] Cloud save synchronization
- [ ] Conflict resolution for cloud saves
- [x] Auto-save with configurable triggers
- [x] Incremental/delta saves
- [x] Thumbnails and custom metadata
- [ ] Import/export for cross-platform
16.4 Network Synchronization
- [x] Entity replication
- [x] Component sync strategies (Authoritative, Interpolated, Predicted, OwnerAuthoritative)
- [x] Client-side prediction
- [x] Server reconciliation
- [x] Network plugin foundation (NetworkServerPlugin, NetworkClientPlugin)
- [x] Delta compression for bandwidth optimization
- [x] Entity hierarchy replication
- [x] Ownership transfer
- [x] Late-joiner full snapshots
Phase 17: Advanced Performance
Maximum performance optimizations.
17.1 Parallelization
- [x] Parallel system execution
- [x] Job system integration
- [x] Thread-safe command buffers
- [x] Parallel query iteration
- [x] Dependency graph for safe parallelism
17.2 Native AOT Support
- [x] Trimming-safe APIs
- [x] Source generator compatibility with AOT
- [x] Reflection-free serialization
- [x] Benchmark AOT vs JIT performance (tracked in #366)
17.3 Advanced Spatial Partitioning
- [x] Configurable grid sizes
- [x] Hierarchical spatial structures
- [x] Broadphase/narrowphase separation
- [x] Spatial query optimization
17.4 Component Composition
- [x] Component inheritance/mixins
- [x] Component bundles (group common components)
- [x]
[Bundle]attribute for source generation
Phase 18: Deterministic Replay System
Record and replay gameplay for debugging and playtesting.
18.1 Recording System
- [x]
ReplayRecorderclass - [x] Record all inputs (keyboard, mouse, gamepad)
- [x] Capture non-deterministic events (random seeds, timestamps)
- [x] Log system execution order
- [x] Interval-based snapshot capture
- [x] Delta compression for storage efficiency
18.2 Playback Engine
- [x]
ReplayPlayerclass - [x] Frame-perfect input replay
- [x] Deterministic execution guarantee
- [x] State restoration at any point
- [x] Cross-machine determinism
18.3 Timeline Controls
- [x]
ReplayTimelineclass - [x] Play/pause/stop
- [x] Timeline scrubbing (seek to any frame)
- [x] Speed adjustment (0.25x to 4x)
- [x] Frame stepping (forward/backward)
18.4 Playtesting Infrastructure
- [x] Session recording for playtesters
- [ ] Web distribution of test builds
- [x] Crash reporting integration
- [x] Player feedback collection
- [x] Debug visualization during replay
Phase 19: IDE Extension
Developer tooling for Visual Studio / VS Code / Rider.
19.1 Code Navigation
- [ ] Go to component/system definition
- [ ] Find all references
- [ ] Component/system usage analysis
19.2 Refactoring Support
- [ ] Rename component (updates all usages)
- [ ] Extract component from entity
- [ ] Inline component
19.3 Visualization Tools
- [ ] Entity hierarchy tree view
- [ ] Archetype visualization
- [ ] System dependency graph
- [ ] Query visualization
19.4 Debugging Integration
- [ ] Entity inspector panel
- [ ] Component value editing
- [ ] System execution visualizer
- [ ] Breakpoints on component changes
Phase 20: KESL Shader Language
Custom shader language with visual graph editor integration.
20.1 Compiler
- [x] Lexer and tokenization
- [x] Parser and AST generation
- [x] GLSL code generation
- [x] C# binding generation
- [x] HLSL backend for DirectX
- [x] Improved error messages with source locations
20.2 Visual Graph Editor
- [x] Node-based graph editor UI
- [x] Bezier curve connections
- [x] Extensible node type system
- [x] Undo/redo support
- [x] Context menus
- [x] Hot-reload support
- [ ] IDE syntax highlighting
20.3 Runtime
- [x] Runtime shader abstractions
- [x] Shader parameter binding
- [ ] Shader variant compilation
Desktop Scene Editor
Status: Active Development
A native desktop game editor using Silk.NET/OpenGL, similar to Unity/Godot.
Editor Infrastructure
- [x] Native desktop application (KeenEyes.Editor)
- [x] Dockable panel system with layout persistence
- [x] Keyboard shortcuts system
- [x] Settings and preferences
- [x] Hot reload via AssemblyLoadContext
Scene Editor
- [x] 3D viewport with OpenGL rendering
- [x] Transform gizmos (translate, rotate, scale)
- [x] Entity hierarchy panel
- [x] Multi-select and group operations
- [x] Undo/redo system (command pattern)
Inspector & Properties Panel
- [x] Component introspection (reflection-based)
- [x] PropertyDrawer system for custom editors
- [x] Built-in drawers (primitives, vectors, colors)
- [ ] Multi-entity editing
- [ ] Property search and filtering
Project Management
- [x] Project panel (asset browser)
- [x] Console panel (logs and messages)
- [ ] Asset import pipeline
- [x] Scene file format (.kescene)
Play Mode
- [x] Run game in editor
- [x] Pause and inspect state
- [x] World snapshot/restore
- [ ] Live entity/component editing
- [ ] Performance overlay
Plugin System
- [x] IEditorPlugin interface
- [x] Capability-based extensions (Panel, Menu, Inspector, Viewport, etc.)
- [x] Plugin lifecycle management
- [x] NuGet-based plugin installation
- [x] Plugin security and sandboxing
Future: Companion Packages
Optional packages that extend KeenEyes:
Implemented Plugins
| Package | Purpose | Status |
|---|---|---|
KeenEyes.Spatial |
Quadtree/octree spatial partitioning | ✅ Complete |
KeenEyes.Physics |
BepuPhysics integration | ✅ Complete |
KeenEyes.Persistence |
Serialization with encryption | ✅ Complete |
KeenEyes.Parallelism |
Parallel system execution | ✅ Complete |
KeenEyes.Graphics |
Silk.NET OpenGL rendering | ✅ Complete |
KeenEyes.Logging |
Pluggable logging providers | ✅ Complete |
KeenEyes.AI |
FSM, Behavior Trees, Utility AI | ✅ Complete |
KeenEyes.Navigation |
Pathfinding (NavMesh + Grid A*) | ✅ Complete |
KeenEyes.Localization |
Multi-language text & assets (JSON + ICU + RTL) | ✅ Complete |
KeenEyes.Network |
Multiplayer/networking plugin | ✅ Complete |
KeenEyes.Replay |
Deterministic replay recording/playback | ✅ Complete |
Planned Plugins (Milestones Created)
| Package | Purpose | Milestone |
|---|---|---|
KeenEyes.Graphics.Abstractions |
Graphics contracts (IRenderer, IRenderPipeline) | #14 |
KeenEyes.Input.Abstractions |
Input contracts (IInputSource, IInputManager) | #14 |
KeenEyes.Input |
Silk.NET input implementation | #14 |
KeenEyes.UI |
Retained-mode UI as ECS entities | #15 |
KeenEyes.Audio |
OpenAL audio via Silk.NET | #16 |
KeenEyes.Particles |
High-performance particle systems | #18 |
KeenEyes.Assets |
Reference-counted asset management | #19 |
KeenEyes.Animation |
Sprite, skeletal, and property animation | #20 |
Research Required
| Package | Purpose | Status |
|---|---|---|
KeenEyes.Scenes |
World streaming & additive loading | Partial (SceneManager exists, streaming pending) |
Additional Plugins from OrionECS
| Plugin | Purpose |
|---|---|
KeenEyes.Canvas2D |
2D canvas rendering |
KeenEyes.Interaction |
User interaction systems |
KeenEyes.Budgets |
Resource budget management |
KeenEyes.ComponentPropagation |
Parent-to-child component inheritance |
KeenEyes.TransformPropagation |
Automatic transform inheritance |
Feature Count Summary
Engine Core (Phases 1-11)
| Category | Features | Status |
|---|---|---|
| Core Entity Operations | 7 | ✅ Complete |
| Singletons/Resources | 5 | ✅ Complete |
| Command Buffer | 5 | ✅ Complete |
| Archetype Storage | 8 | ✅ Complete |
| Query Caching | 3 | ✅ Complete |
| Entity Hierarchy | 7 | ✅ Complete |
| Event System | 6 | ✅ Complete |
| Change Tracking | 5 | ✅ Complete |
| System Enhancements | 12 | ✅ Complete |
| Plugin System | 15 | ✅ Complete |
| Inter-System Messaging | 6 | ✅ Complete |
| Prefabs | 6 | ✅ Complete |
| Entity Tags | 6 | ✅ Complete |
| Component Validation | 4 | ✅ Complete |
| Serialization | 6 | ✅ Complete |
| Subtotal | ~99 | ✅ Complete |
Developer Experience (Phases 12-14)
| Category | Features | Status |
|---|---|---|
| Log Provider Architecture | 4 | ✅ Complete |
| Built-in Log Providers | 4 | ✅ Complete |
| Logging Features | 6 | ✅ Complete |
| ECS-Specific Logging | 5 | ✅ Complete |
| Debug Mode | 3 | ✅ Complete |
| Profiling | 4 | ✅ Complete |
| Visualization | 3 | ✅ Complete |
| Test World Builder | 5 | ✅ Complete |
| Assertion Helpers | 6 | Partial (5/6) |
| Mock Utilities | 4 | ✅ Complete |
| Snapshot Testing | 4 | ✅ Complete |
| Test Fixtures | 4 | ✅ Complete |
| Subtotal | ~52 | Mostly Complete |
Production & Advanced (Phases 16-17)
| Category | Features | Status |
|---|---|---|
| Multi-World Support | 4 | Partial (2/4) |
| Schema Evolution | 4 | ✅ Complete |
| Enhanced Save/Load | 11 | Mostly Complete (8/11, cloud sync + import/export pending) |
| Network Sync | 9 | ✅ Complete (KeenEyes.Network) |
| Parallelization | 5 | ✅ Complete |
| Native AOT | 4 | ✅ Complete |
| Advanced Spatial | 4 | ✅ Complete |
| Component Composition | 3 | ✅ Complete |
| Subtotal | ~44 | Mostly Complete |
Tooling (Phases 18-20)
| Category | Features | Status |
|---|---|---|
| Replay Recording | 6 | ✅ Complete |
| Replay Playback | 5 | ✅ Complete |
| Timeline Controls | 5 | ✅ Complete |
| Playtesting Infrastructure | 5 | Partial (4/5) |
| IDE Code Navigation | 3 | Pending |
| IDE Refactoring | 3 | Pending |
| IDE Visualization | 4 | Pending |
| IDE Debugging | 4 | Pending |
| KESL Compiler | 6 | ✅ Complete |
| KESL Graph Editor | 7 | Partial (6/7) |
| KESL Runtime | 3 | Partial (2/3) |
| Subtotal | ~51 | Partial |
Desktop Scene Editor
| Category | Features | Status |
|---|---|---|
| Editor Infrastructure | 5 | ✅ Complete |
| Scene Editor | 5 | ✅ Complete |
| Inspector Panel | 5 | Partial (3/5) |
| Project Management | 4 | Partial (3/4) |
| Play Mode | 5 | Partial (3/5) |
| Plugin System | 5 | ✅ Complete |
| Subtotal | ~29 | Active Development |
Grand Total: ~275+ features
Design Principles
When implementing these features, maintain KeenEyes's core principles:
- No Static State - All state is per-world instance
- Respect User Intent - Provide helpers, let users wire things up
- Performance First - Zero/minimal allocations in hot paths
- Source Generators for Ergonomics - Reduce boilerplate, maintain performance
- Components are Structs - Cache-friendly value semantics
- Entities are IDs - Lightweight
(int Id, int Version)with staleness detection
Source Generator Opportunities
Source generators can eliminate boilerplate, enable AOT compatibility, and provide compile-time safety. Below are all features that could benefit from source generation.
Already Planned (from CLAUDE.md)
| Attribute | Generates |
|---|---|
[Component] |
WithComponentName(...) fluent builder methods |
[TagComponent] |
Parameterless WithTagName() methods |
[System] |
Metadata properties (Phase, Order, Group) |
[Query] |
Efficient query iterators |
Core ECS Enhancements
Component Registration (Phase 1)
[Component]
public partial struct Position { public float X, Y; }
// Generates:
// - ComponentId constant
// - WithPosition(float x, float y) extension on EntityBuilder
// - Ref accessor helpers
Singleton Accessors (Phase 1)
[Singleton]
public partial class GameTime { public float Delta; public float Total; }
// Generates:
// - world.GameTime property (typed accessor)
// - Compile-time existence check
Query Optimization (Phase 2)
[Query]
public partial struct MovementQuery : IQuery<Position, Velocity> { }
// Generates:
// - Specialized enumerator for this component combination
// - Archetype-aware iteration
// - Inline component access (no dictionary lookups)
Validation & Safety
Component Dependencies (Phase 10)
[Component]
[RequiresComponent(typeof(Transform))]
[ConflictsWith(typeof(StaticBody))]
public partial struct RigidBody { }
// Generates:
// - Compile-time warnings if dependencies not added
// - Runtime validation in debug mode
// - EntityBuilder guards
Entity Tags (Phase 9)
[Tags]
public enum EntityTags { Player, Enemy, Projectile, Pickup }
// Generates:
// - Type-safe tag constants
// - .WithTag(EntityTags.Player) overload
// - .HasTag(EntityTags.Enemy) overload
// - Query: .WithTag(EntityTags.Player)
Serialization & Networking
Component Serialization (Phase 11)
[Component(Serializable = true)]
public partial struct Health { public int Current; public int Max; }
// Generates:
// - Binary serializer/deserializer (reflection-free)
// - JSON serializer (optional)
// - Schema version tracking
// - AOT-compatible serialization
Network Replication (Phase 16)
[Component]
[Replicated(Interpolated = true)]
public partial struct NetworkTransform { public float X, Y, Rotation; }
// Generates:
// - Delta compression serializer
// - Interpolation helpers
// - Ownership/authority checks
// - Bandwidth estimation
Schema Migration (Phase 16)
[Component(Version = 2)]
[MigrateFrom(typeof(HealthV1), nameof(MigrateFromV1))]
public partial struct Health { public int Current; public int Max; public int Shield; }
// Generates:
// - Version detection during deserialization
// - Automatic migration pipeline
// - Backward compatibility layer
Systems & Execution
System Dependencies (Phase 5)
[System(Phase = SystemPhase.Update, Order = 10)]
[RunAfter(typeof(InputSystem))]
[RunBefore(typeof(RenderSystem))]
[WriteComponents(typeof(Position))]
[ReadComponents(typeof(Velocity))]
public partial class MovementSystem : SystemBase { }
// Generates:
// - Dependency graph edges
// - Parallelization safety analysis
// - Automatic system ordering
System Queries (Phase 5)
public partial class MovementSystem : SystemBase
{
[Query]
private partial IEnumerable<(Entity, ref Position, ref readonly Velocity)> GetMovables();
}
// Generates:
// - Optimized query method implementation
// - Cached query descriptor
// - Read/write component tracking
Component Bundles (Phase 17)
[Bundle]
public partial struct TransformBundle
{
public Position Position;
public Rotation Rotation;
public Scale Scale;
}
// Generates:
// - .WithTransformBundle(pos, rot, scale) on EntityBuilder
// - Bundle-aware archetype optimization
// - Shorthand query: Query<TransformBundle>()
Events & Change Tracking
Reactive Components (Phase 4)
[Component]
[TrackChanges]
public partial struct Health { public int Current; public int Max; }
// Generates:
// - Automatic dirty flag management
// - OnHealthChanged event hookup
// - Previous value tracking (optional)
Event Handlers (Phase 4)
public partial class DamageSystem : SystemBase
{
[OnComponentChanged(typeof(Health))]
private partial void HandleHealthChanged(Entity entity, Health oldValue, Health newValue);
}
// Generates:
// - Event subscription in OnInitialize
// - Unsubscription in Dispose
// - Type-safe handler wiring
Prefabs & Templates
Prefab Definition (Phase 8)
[Prefab("Enemy/Goblin")]
public partial struct GoblinPrefab
{
public Position Position;
public Health Health = new() { Current = 100, Max = 100 };
public Enemy EnemyTag;
}
// Generates:
// - Prefab registration on world startup
// - world.SpawnGoblin(position) typed method
// - Override support: world.SpawnGoblin(position, health: new(...))
Testing Utilities (Phase 14)
Test Assertions
[Component]
public partial struct Health { public int Current; public int Max; }
// Generates (in KeenEyes.Testing):
// - entity.ShouldHaveHealth()
// - entity.ShouldHaveHealth(h => h.Current > 0)
// - health.ShouldEqual(expected)
Logging & Diagnostics
Log Categories (Phase 12)
[LogCategory]
public static partial class EcsLogs
{
public static partial void EntityCreated(Entity entity);
public static partial void ComponentAdded<T>(Entity entity);
public static partial void SystemExecuted(string name, double ms);
}
// Generates:
// - High-performance logging methods
// - Structured log parameters
// - Compile-time log level filtering
// - Zero allocation when disabled
Editor & Inspector (Long-term)
Property Metadata
[Component]
public partial struct EnemyConfig
{
[Range(0, 100)]
[Tooltip("Movement speed in units per second")]
public float Speed;
[Header("Combat")]
[Min(1)]
public int Damage;
[ColorPicker]
public uint TintColor;
}
// Generates:
// - Inspector UI descriptors
// - Validation code
// - Default value initialization
// - Undo/redo support metadata
Summary: Generator-Enhanced Attributes
| Attribute | Phase | Purpose |
|---|---|---|
[Component] |
1 | Builder methods, registration |
[TagComponent] |
1 | Zero-size tag helpers |
[Singleton] |
1 | Typed singleton accessors |
[Query] |
2 | Optimized query iterators |
[Bundle] |
17 | Component grouping |
[System] |
5 | Metadata, ordering |
[RunBefore] / [RunAfter] |
5 | System dependencies |
[ReadComponents] / [WriteComponents] |
5 | Parallelization safety |
[RequiresComponent] |
10 | Validation |
[ConflictsWith] |
10 | Validation |
[TrackChanges] |
4 | Change detection |
[OnComponentChanged] |
4 | Event handlers |
[Serializable] |
11 | Binary/JSON serialization |
[Replicated] |
16 | Network sync |
[MigrateFrom] |
16 | Schema evolution |
[Prefab] |
8 | Entity templates |
[Tags] |
9 | Type-safe string tags |
[LogCategory] |
12 | Structured logging |
[Range], [Tooltip], etc. |
Editor | Inspector metadata |
Implementation Priority
High Value, Lower Complexity:
[Component]enhancements (builder methods) - already started[Query]optimized iterators - major perf win[Serializable]reflection-free serialization - AOT requirement[LogCategory]high-perf logging - common need
High Value, Higher Complexity:
5. [System] with dependency analysis - enables parallelization
6. [TrackChanges] reactive components - common pattern
7. [Prefab] typed spawning - great DX
8. [Replicated] network code gen - significant boilerplate reduction
Future/Editor:
9. Inspector metadata attributes - editor-dependent
10. [MigrateFrom] schema evolution - production need
C#/.NET Features to Leverage
Modern .NET provides powerful features for building high-performance ECS frameworks. This section maps relevant .NET features to each roadmap phase.
Phase 1: Core Completion
| Feature | Usage |
|---|---|
ref returns |
Zero-copy component access: ref T Get<T>(Entity e) |
in parameters |
Read-only refs for queries: in Position pos |
Span<T> |
Stack-allocated component lists in builders |
readonly record struct |
Entity type: readonly record struct Entity(int Id, int Version) |
| Generic constraints | where T : struct, IComponent |
Unsafe.SizeOf<T>() |
Component size calculation without boxing |
CollectionsMarshal.GetValueRefOrAddDefault |
Fast dictionary access |
// Example: Zero-copy component access
public ref T Get<T>(Entity entity) where T : struct, IComponent
{
ref var storage = ref CollectionsMarshal.GetValueRefOrNullRef(components, entity.Id);
return ref Unsafe.As<byte, T>(ref storage[offset]);
}
Phase 2: Archetype Storage
| Feature | Usage |
|---|---|
Span<T> / Memory<T> |
Contiguous component storage views |
ArrayPool<T>.Shared |
Pooled archetype chunk allocation |
Unsafe.As<TFrom, TTo>() |
Type punning for generic component access |
MemoryMarshal.Cast<T1, T2>() |
Reinterpret component arrays |
NativeMemory.AlignedAlloc() |
Cache-aligned allocations |
[SkipLocalsInit] |
Avoid zeroing large arrays |
[InlineArray(N)] |
Fixed-size inline component storage (C# 12) |
// Example: Archetype chunk with pooled storage
public sealed class ArchetypeChunk
{
private byte[] buffer = ArrayPool<byte>.Shared.Rent(ChunkSize);
public Span<T> GetComponentSpan<T>(int offset, int count) where T : struct
=> MemoryMarshal.Cast<byte, T>(buffer.AsSpan(offset, count * Unsafe.SizeOf<T>()));
}
Phase 3: Entity Hierarchy
| Feature | Usage |
|---|---|
Span<Entity> |
Return children without allocation |
stackalloc |
Small child lists on stack |
ValueListBuilder<T> |
Growing lists without heap allocation |
Phase 4: Events & Change Tracking
| Feature | Usage |
|---|---|
Action<T> / Func<T> |
Lightweight event delegates |
WeakReference<T> |
Prevent memory leaks in event subscriptions |
ConditionalWeakTable<K,V> |
Associate change tracking data without modifying types |
[Flags] enum |
Dirty flag bitfields |
// Example: Weak event subscription
public sealed class EventBus<T>
{
private readonly List<WeakReference<Action<T>>> handlers = [];
public void Subscribe(Action<T> handler)
=> handlers.Add(new WeakReference<Action<T>>(handler));
}
Phase 5: System Enhancements
| Feature | Usage |
|---|---|
IComparer<T> |
System priority sorting |
TopologicalSort |
Dependency-based ordering |
Lazy<T> |
Deferred system initialization |
[CallerMemberName] |
Automatic system naming |
Phase 6: Plugin System
| Feature | Usage |
|---|---|
AssemblyLoadContext |
Plugin isolation and unloading |
Type.GetType() with assembly |
Cross-assembly type resolution |
Activator.CreateInstance<T>() |
Plugin instantiation |
| Generic interfaces | IWorldPlugin, IPluginContext |
Phase 7: Inter-System Messaging
| Feature | Usage |
|---|---|
System.Threading.Channels |
High-perf async message queues |
Channel<T>.CreateUnbounded() |
Lock-free message passing |
ConcurrentQueue<T> |
Simple thread-safe queues |
IObservable<T> / IObserver<T> |
Reactive message patterns |
// Example: High-performance message bus
public sealed class MessageBus
{
private readonly Channel<object> channel = Channel.CreateUnbounded<object>(
new UnboundedChannelOptions { SingleReader = true, SingleWriter = false });
}
Phase 8: Prefabs & Templates
| Feature | Usage |
|---|---|
Expression<T> |
Compile prefab factories at runtime |
Delegate.CreateDelegate() |
Fast delegate creation |
FrozenDictionary<K,V> |
Immutable prefab registry (.NET 8+) |
Phase 9: Entity Tags
| Feature | Usage |
|---|---|
FrozenSet<string> |
Immutable tag lookups (.NET 8+) |
StringComparer.Ordinal |
Fast string comparison |
string.GetHashCode(StringComparison) |
Consistent hashing |
HashSet<string> |
Tag storage per entity |
Phase 10: Component Validation
| Feature | Usage |
|---|---|
| Roslyn Analyzers | Compile-time validation rules |
DiagnosticDescriptor |
Custom compiler warnings |
[Conditional("DEBUG")] |
Debug-only validation |
Phase 11: Serialization
| Feature | Usage |
|---|---|
System.Text.Json source generators |
AOT-friendly JSON |
JsonSerializerContext |
Compile-time serialization |
BinaryReader / BinaryWriter |
Fast binary I/O |
IBufferWriter<byte> |
Zero-copy serialization |
MemoryPack (library) |
Fastest binary serializer |
ReadOnlySpan<byte> |
Zero-copy deserialization |
// Example: Source-generated JSON serialization
[JsonSerializable(typeof(WorldSnapshot))]
[JsonSourceGenerationOptions(WriteIndented = false)]
public partial class SnapshotJsonContext : JsonSerializerContext { }
Phase 12: Logging
| Feature | Usage |
|---|---|
Microsoft.Extensions.Logging |
Standard logging abstraction |
LoggerMessage.Define() |
High-perf cached log delegates |
[LoggerMessage] attribute |
Source-generated logging (.NET 6+) |
ILogger<T> |
Category-based logging |
EventSource |
ETW tracing on Windows |
// Example: High-performance logging
public static partial class EcsLoggers
{
[LoggerMessage(Level = LogLevel.Debug, Message = "Entity {EntityId} created")]
public static partial void EntityCreated(ILogger logger, int entityId);
}
Phase 13: Debugging & Profiling
| Feature | Usage |
|---|---|
Stopwatch.GetTimestamp() |
High-resolution timing |
Stopwatch.GetElapsedTime() |
Allocation-free elapsed time (.NET 7+) |
DiagnosticSource |
Structured diagnostics |
Activity |
Distributed tracing |
EventCounter |
Performance counters |
GC.GetAllocatedBytesForCurrentThread() |
Per-thread allocation tracking |
[DebuggerDisplay] |
Better debugger experience |
[DebuggerTypeProxy] |
Custom debugger views |
// Example: Zero-allocation timing
public readonly struct SystemTimer
{
private readonly long start = Stopwatch.GetTimestamp();
public TimeSpan Elapsed => Stopwatch.GetElapsedTime(start);
}
Phase 14: Testing
| Feature | Usage |
|---|---|
xUnit / NUnit |
Test frameworks |
[Theory] / [InlineData] |
Parameterized tests |
Verify (library) |
Snapshot testing |
NSubstitute / Moq |
Mocking |
BenchmarkDotNet |
Performance regression tests |
ITestOutputHelper |
Test logging |
Phase 16: Production Readiness
| Feature | Usage |
|---|---|
| Native AOT | Ahead-of-time compilation |
[DynamicallyAccessedMembers] |
Trimming hints |
[RequiresUnreferencedCode] |
Mark reflection-heavy APIs |
[UnconditionalSuppressMessage] |
Suppress false trimming warnings |
PublishAot=true |
Enable AOT publishing |
JsonSerializer with context |
AOT-safe JSON |
| Source generators | Reflection-free code gen |
<!-- Example: AOT-compatible project settings -->
<PropertyGroup>
<PublishAot>true</PublishAot>
<TrimMode>full</TrimMode>
<IlcOptimizationPreference>Speed</IlcOptimizationPreference>
</PropertyGroup>
Phase 17: Advanced Performance
| Feature | Usage |
|---|---|
Vector<T> / Vector128<T> |
SIMD operations |
Parallel.ForEach() |
Parallel iteration |
IThreadPoolWorkItem |
Custom thread pool work |
ThreadPool.UnsafeQueueUserWorkItem() |
Low-overhead scheduling |
SpinLock / SpinWait |
Lock-free synchronization |
Interlocked.* |
Atomic operations |
[MethodImpl(AggressiveInlining)] |
Force inlining |
[MethodImpl(AggressiveOptimization)] |
Tier-1 JIT immediately |
| Hardware intrinsics | System.Runtime.Intrinsics |
// Example: SIMD-accelerated position update
public static void UpdatePositions(Span<Position> positions, Span<Velocity> velocities, float dt)
{
var dtVec = Vector256.Create(dt);
for (int i = 0; i <= positions.Length - Vector256<float>.Count; i += Vector256<float>.Count)
{
var pos = Vector256.LoadUnsafe(ref Unsafe.As<Position, float>(ref positions[i]));
var vel = Vector256.LoadUnsafe(ref Unsafe.As<Velocity, float>(ref velocities[i]));
var result = Vector256.FusedMultiplyAdd(vel, dtVec, pos);
result.StoreUnsafe(ref Unsafe.As<Position, float>(ref positions[i]));
}
}
Phase 18: Deterministic Replay
| Feature | Usage |
|---|---|
BinaryReader / BinaryWriter |
Efficient binary I/O |
GZipStream / BrotliStream |
Compression |
RandomNumberGenerator |
Secure seed generation |
System.Random with seed |
Deterministic randomness |
FileStream with FileOptions.Asynchronous |
Async file I/O |
PipeReader / PipeWriter |
High-perf streaming |
Phase 19: IDE Extension
| Feature | Usage |
|---|---|
Roslyn IIncrementalGenerator |
Incremental source generation |
Microsoft.CodeAnalysis |
Code analysis APIs |
DiagnosticAnalyzer |
Custom warnings/errors |
CodeFixProvider |
Automated code fixes |
ISourceGenerator |
Legacy source generation |
| Language Server Protocol | IDE-agnostic tooling |
General Best Practices
| Practice | Description |
|---|---|
readonly struct |
Prevents defensive copies |
record struct |
Value equality + deconstruction |
init properties |
Immutable after construction |
required members |
Enforce initialization (C# 11) |
file scoped types |
Reduce namespace pollution (C# 11) |
| Collection expressions | [1, 2, 3] syntax (C# 12) |
| Primary constructors | Less boilerplate (C# 12) |
params Span<T> |
Stack-allocated varargs (C# 13) |
allows ref struct |
Generic ref struct support (C# 13) |
Lock object |
Better than object for locking (.NET 9) |
.NET Version Requirements
| Feature | Minimum Version |
|---|---|
Span<T>, Memory<T> |
.NET Core 2.1 |
| Default interface methods | .NET Core 3.0 |
| Source generators | .NET 5.0 |
LoggerMessage attribute |
.NET 6.0 |
Stopwatch.GetElapsedTime() |
.NET 7.0 |
FrozenDictionary/Set |
.NET 8.0 |
| Native AOT (production) | .NET 8.0 |
params Span<T> |
.NET 9.0 |
Lock class |
.NET 9.0 |
| KeenEyes Target | .NET 10 |