Important! Dont forget to use DEBUG builds for development and RELEASE builds in production: all internal error checks / exception throwing works only in DEBUG builds and eleminated for performance reasons in RELEASE.

Main parts of ecs

Component

Container for user data without / with small logic inside. Can be used any user class without any additional inheritance:

class WeaponComponent {
public int Ammo;
public string GunName;
}

Important! Dont forget to manually init all fields of new added component. Default value initializers will not work due all components can be reused automatically multiple times through builtin pooling mechanism (no destroying / creating new instance for each request for performance reason).

Important! Dont forget to cleanup reference links to instances of another components / engine classes before removing components from entity, otherwise it can lead to memory leaks.

By default all marshal-by-reference typed fields of component (classes in common case) will be checked for null on removing attempt in DEBUG-mode. If you know that you have object instance that should be not null (preinited collections for example) - [EcsIgnoreNullCheck] attribute can be used for disabling these checks.

Entity

Сontainer for components. Implemented with int id-s for more simplified api:

System

class WeaponSystem : IEcsPreInitSystem, IEcsInitSystem {
void IEcsPreInitSystem.PreInitialize () {
// Will be called once during world initialization and before IEcsInitSystem.Initialize.
}
void IEcsInitSystem.Initialize () {
// Will be called once during world initialization.
}
void IEcsInitSystem.Destroy () {
// Will be called once during world destruction.
}
void IEcsPreInitSystem.PreDestroy () {
// Will be called once during world destruction and after IEcsInitSystem.Destroy.
}
}

Important: Any filter supports up to 4 component types as “include” constraints and up to 2 component types as “exclude” constraints. Shorter constraints - better performance.

Important: If you will try to use 2 filters with same components but in different order - you will get exception with detailed info about conflicted types, but only in DEBUG mode. In RELEASE mode all checks will be skipped.

EcsWorld

Root level container for all entities / components, works like isolated environment.

Important: Do not forget to call EcsWorld.Dispose method when instance will not be used anymore.

I do not need dependency injection through Reflection (I heard, it’s very slooooow! / I want to use my own way to inject). How I can do it?

Builtin Reflection-based DI can be removed with LEOECS_DISABLE_INJECT preprocessor define:

No EcsInject attribute.

No automatic injection for EcsWorld and EcsFilter<T> fields.

Less code size.

EcsWorld should be injected somehow (for example, through constructor of system), EcsFilter<T> data can be requested through EcsWorld.GetFilter<T> method.

I do not like foreach-loops, I know that for-loops are faster. How I can use it?

Current implementation of foreach-loop fast enough (custom enumerator, no memory allocation), performance differences can be found on 10k items and more. Anyway, for-loop can be used instead foreach-loop as next in-place replacement without issues:

foreach (var i in _filter)

can be replaced with

for (int i = 0, iMax = _filter.EntitiesCount; i < iMax; i++)

I copy&paste my reset components code again and again. How I can do it in other manner?

If you want to simplify your code and keep reset-code in one place, you can use IEcsAutoResetComponent interface for components: