... the little ECS that loves you back!
The Entity-Component System (ECS) is an architectural pattern that champions composition over inheritance. Entities are small, unique identifiers, and Components are data attached to them. The term Systems often refers to the logic that operates on this data.
Typical ECS Concepts
(these are what makes many ECS architectures tick)
Entities exist in a World.
Entities can be spawned solo, or in bulk with pre-configured components.
Components can be added to / removed from Entities.
Components can be backed by any type; Value or Reference, even empty structs
.
Queries filter Entities using Match Expressions.
This matching is done by Component types and targets (presence or absence).
Code Acts on Component data in tight, optimized loops.
You provide logic in Runner Delegates which are executed on a single or multiple threads.
Component data is always kept contiguous* in Memory.
Structurally similar Entities are packed into Archetypes for improved cache locality.
* per Archetype
Unique fennecs Concepts
(weird cool stuff that gets us all wide-eyed and bushy tailed)
Streams expose fast Iteration and SIMD Operations
Quickly & safely iterate entities, or modify Components in bulk, or process entire memory blocks.
Relations are Components with an Entity Target.
These add expressive, powerful grouping semantics. Relations can be backed by any type.
Links are Components backed by an Object Target.
Group Entities logically and in memory by linking them to shared data, like a physics world.
Queries expose Structural Changes (just as Entities do)
Efficiently and safely add, remove from individual Entities or entire matched Queries.
Runners let you pass uniform data to your Workloads.
A tiny tidbit that streamlines the process of passing data into a job or run.
Worlds, Queries, and Streams implement IEnumerable<>
.
It's amazing to be able to every now and then just LINQ it up and be done somewhere.
There are no formalized Systems.
You have a higher degree of freedom when and how to interact with Queries and Stream Views.
There is no formalized Scheduler.
Parallel Jobs execute synchronously, as fast as possible. Runners are invokable anytime, anywhere.
Structural Changes may be submitted* at any time.
Worlds process them at the end of a Query Runner's scope, otherwise immediately.
* never type EndInitializationEntityCommandBufferSystem
nor AddJobHandleForProducer(JobHandle)
again! 🦊