TrimKit.EntityOrchestration 1.0.0

dotnet add package TrimKit.EntityOrchestration --version 1.0.0
                    
NuGet\Install-Package TrimKit.EntityOrchestration -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TrimKit.EntityOrchestration" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TrimKit.EntityOrchestration" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="TrimKit.EntityOrchestration" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add TrimKit.EntityOrchestration --version 1.0.0
                    
#r "nuget: TrimKit.EntityOrchestration, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package TrimKit.EntityOrchestration@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=TrimKit.EntityOrchestration&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=TrimKit.EntityOrchestration&version=1.0.0
                    
Install as a Cake Tool

TrimKit.EntityOrchestration

TrimKit.EntityOrchestration provides a lightweight, dependency-free way to manage entities and systems in a structured and deterministic manner - bridging the gap between classic OOP approach and modern ECS patterns.

You might ask, But isn't this just another ECS implementation?

Not quite - there's no "C" here. You work with traditional inheritance hierarchies and rich object models, just like in classic OOP design.

The problem with that traditional approach, however, is scalability: once your project grows, reasoning about behavior and dependencies quickly becomes painful. ECS frameworks solve this by enforcing rigid data decomposition - but at the cost of constant micromanagement, boilerplate, and a steep learning curve.

In short, Entity Orchestration aims to strike the balance somewhere in the middle.

It gives you rigid structure, determinism, and modularity of an ECS-style approach - but without forcing your game into hundreds of micro-components. You keep your natural inheritance hierarchies, while gaining predictable update flow and a unified orchestration layer that keeps everything tidy and maintainable.

Features

  • Deterministic and order-based system execution
  • Strict or flexible entity categorization
  • Type-safe queries for entities by registered types
  • Collections can be modified during execution freely
  • No external dependencies

Installation

Use provided nuget package or download the source.

NuGet

🔧 dotnet add package TrimKit.EntityOrchestration

Quick start

First, create the entity manager and register types you want to separate entities into (this also allows you to query them by type).

var entityManager = new EntityManager(strict: true)	
    .RegisterType<Character>()
	.RegisterType<Player>() // inherits from Character
    .RegisterType<Enemy>() // Inherits from Character
	.RegisterType<Prop>();

entityManager.Initialize();

Add and query entities.

// add some entities
entityManager.Add(new Player("Player 1"));
entityManager.Add(new Enemy("Rat"));
entityManager.Add(new Enemy("Orc"));
entityManager.Add(new Prop("Rock"));

// get entities of type Player (in our case just one)
var players = entityManager.GetByType<Player>();

// this will return two enemies
var enemies = entityManager.GetByType<Enemy>();

// this will return both: player AND enemies, since they both inherit from Character
var characters = entityManager.GetByType<Character>();

Now, let's use EntityManager together with Orchestrator.

First, let's create a system.

public class MovementSystem : BaseSystem
{
    public override void OnUpdate(EntityManager em, GameContext ctx)
    {
        // example logic
        var players = em.GetByType<Player>();
        // ...
    }
}

And then register it.

// we create orchestrator with GameContext and pass our existing entityManager into the constructor
var orchestrator = new Orchestrator<GameContext>(entityManager);

// next we can define some systems and initialize
orchestrator.AddSystem<MovementSystem>()
			.AddSystem<CombatSystem>()
			.AddSystem<AnotherSystem>()
			.AddSystem<WhateverSystem>()
		    .Initialize();

Finally, simply call Update in your game loop and pass your game context, so systems can access what they need.

orchestrator.Update(gameContext);

API Overview

EntityManager

Method / Property Description
EntityManager(bool strict = false) Creates a new manager; in strict mode only registered types are allowed.
EntityManager RegisterType<T>() Registers a base entity type for categorization.
void Initialize() Locks registration and enables runtime operations.
void Add(BaseEntity entity) Adds an entity and associates it with matching registered types.
void Remove(BaseEntity entity) Removes an entity from all collections.
void RemoveDeleted() Removes entities marked as deleted.
void RemoveAll() Clears all entities.
IReadOnlyList<BaseEntity> GetAll(bool excludeDeleted = true) Returns all entities.
IReadOnlyList<T> GetByType<T>(bool excludeDeleted = true) Returns all entities of a specific type.
IReadOnlyList<BaseEntity> GetOther(bool excludeDeleted = true) Returns entities that don't match any registered type.
int Count(bool excludeDeleted = true) Returns total entity count.

Orchestrator

Method / Property Description
Orchestrator(EntityManager entityManager) Creates an orchestrator that manages systems sharing the same EntityManager.
Orchestrator<TContext> AddSystem<TSystem>() Registers a new system via reflection.
Orchestrator<TContext> AddSystem(BaseSystem system) Registers a new system with manual instance injection.
Orchestrator<TContext> Initialize() Initializes all registered systems.
void Update(TContext context) Executes all active systems sequentially.
Orchestrator<TContext> SetSystemState<TSystem>(bool active) Enables or disables a specific system.
bool IsInitialized Indicates whether the orchestrator is initialized.

Notes

  • The orchestrator executes systems in the order they are added.
  • You must initialize both EntityManager and Orchestrator before using them.
  • Deactivated systems (Active = false) are automatically skipped.
  • EntityManager strict mode ensures strong type control for clean separation and no entities getting into the "other" bucket.
  • You can actually use EntityManager separately without Orchestrator.

Performance

This library is great for small to medium projects, but the fact of difference in performance compared to pure ECS is not lost on me. If you need to iterate over tens of thousands entities every frame and do that FAST you should stick with ECS. There's a reason ECS paradigm exists and is so popular - you just can't beat it in terms of performance. But for everything else... nah.

Changes

  • v1.0 - Initial release.

TrimKit Collection

This library is part of the TrimKit collection - a set of small, focused C# libraries that make game development more enjoyable by reducing the need for boilerplate code and providing simple reusable building blocks that can be dropped into any project.

Each module is independent and can be used standalone or combined with others for a complete lightweight foundation.

Contribution

Contributions are welcome!

You can start with submitting an issue on GitHub.

License

This library is released under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.1

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 199 10/19/2025