Releases: genaray/Arch
1.1.2
Changes
HPQuery
andHPEQuery
, aswell as their parallel counterparts are now calledInlineQuery
,InlineEntityQuery
e.g.- Removed ref iterators since they are incredible slow and can not be inlined #39
- Proper documentation ( generated code is not documented however ) and code style enforcement.
- Performance improvements
New Features
- Classes can now be used as components :)
- Several new overloads for
Index, GetArray, GetSpan, GetFirst
to improve performance and reduce boilerplate code. - Non generic set, get, has, add, remove operations for entities.
- Added enumerator for entity inside chunk enumration.
world.CountEntities
to... count entities which will be targeted by a query.
Non generic entity interaction :
var transform = (object)new Transform { X = 10, Y = 10 };
_entity.Set(transform);
var tramsformReference = (Transform)_entity.Get(typeof(Transform));
// Non generic additional methods
_entity.SetRange(...);
_entity.Has(...);
_entity.HasRange(...);
_entity.Get(...);
_entity.GetRange(...);
_entity.Add(...);
_entity.AddRange(...);
_entity.Remove(...);
_entity.RemoveRange(....);
Overloads for chunk & Chunk enumeration :
foreach (var chunk in _world.Query(in _queryDescription).GetChunkIterator())
{
var refs = chunk.GetFirst<Transform, Velocity>(); // or chunk.GetSpan<Transform, Velocity>(out var trans, out var velos);
foreach (var entity in chunk) // New iteration, automatically iterates backwards over all valid chunk entities.
{
ref var pos = ref Unsafe.Add(ref refs.t0, entity);
ref var vel = ref Unsafe.Add(ref refs.t1, entity);
pos.X += vel.X;
pos.Y += vel.Y;
}
}
1.1.1
Features & Changes
- The
World
can now be modified during queries usingworld.Create
,world.Destroy
,world.Set
,world.Add
,world.Remove
. - Queries and Enumerators now iterate backwards over the entities.
- A new
CommandBuffer
-API is available which combines the previous ones. QueryDescription
now features a new API to reduce boilerplate :var desc = new QueryDescription().WithAll<Position, Velocity>...
.- Added
Arch.Samples
which provides a small usage sample with Arch and Monogame :) - Several small bug fixes and tweaks.
CommandBuffer
You no longer need several CommandBuffers, but a single one. The syntax is now much simpler.
var entity = world.Create<Transform, Rotation, int>();
var bufferedEntity = commandBuffer.Create(new ComponentType[] {typeof(Transform), typeof(Rotation), typeof(int) }); // Later also generic overloads to get rid of arrays.
commandBuffer.Set(in entity, new Transform{ X = 20, Y = 20});
commandBuffer.Add(in entity, new Ai());
commandBuffer.Set(in bufferedEntity, new Transform{ X = 20, Y = 20});
commandBuffer.Add(in bufferedEntity, new Ai());
commandBuffer.Playback();
Acknowledgement
Many thanks to @andreakarasho for fixes and new features ! :)
1.1.0
Features & Changes
PURE_ECS
preprocessor variable for utilizing pure ecs paradigma- Tag Components ( Empty components ) will not influence the amount of possible entities in a certain chunk
Entity.Null
will not anymore create a new null entity each time its acessedComponentType
is now required for several operations to provide additional component data and to prevent lookupsWorld.Id
is now a int and not limited to 255 anymore- Structural changes, adds and removals are now way "smarter" and more efficient
- Made several
World
,Archetype
andChunk
methods internal for a better workflow and less headache World
will internally track entities and some meta data for faster lookup speed and less dictionarys- Major refactoring of internal structures
Archetype
andChunk
are now slimmer and act as pure containers without mapping entities and wasting space. - Several other little tweaks
Pure ECS
Theres a PURE_ECS
preprocessor variable now which sets an entity to exactly one integer and disables all existing entity extension methods. This way the ECS can be accessed by a "pure ecs" mindset, thus more entities fit into one chunk and less unnecessary ballast is dragged around. This may only work with forks since the nugget package version will not have that flag enabled.
Increased lookup speed
Entities are now tracked in one single dictionary inside the world, this one stores archetype and chunk index data to provide instand acess. Compared to previous versions only one single lookup is now required instead of multiple ones, therefore the lookup speed increased by a lot.
Previous version:
Method | Amount | Mean | Error | StdDev | Allocated |
---|---|---|---|---|---|
WorldEntityQuery | 10000 | 513.765 us | 297.3252 us | 16.2974 us | - |
WorldEntityQuery | 100000 | 5,032.846 us | 2,116.4383 us | 116.0091 us | - |
WorldEntityQuery | 1000000 | 50,894.500 us | 1,944.0534 us | 106.5601 us | - |
Current version :
Method | Amount | Mean | Error | StdDev | CacheMisses/Op | Allocated |
---|---|---|---|---|---|---|
WorldEntityQuery | 10000 | 147.660 us | 13.2838 us | 0.7281 us | 746 | - |
WorldEntityQuery | 100000 | 1,726.959 us | 3,058.5935 us | 167.6518 us | 11,761 | - |
WorldEntityQuery | 1000000 | 20,419.798 us | 4,491.2760 us | 246.1820 us | 90,624 | - |
Contributors
@andreakarasho thanks for pointing out issues with commandbuffers and the entity tweaks ! :)
1.0.17
Bug Fixes
Fixed the acessability of CreationBuffer
and ModificationBuffer
constructors, thanks @andreakarasho ! :)
You may now use them like this...
var creationBuffer = new CreationBuffer(world, 1024); <- Initial capacity, not total capacity
world.ParallelQuery(in desc, (in Entity en) => {
var entity = creationBuffer.Create(group);
entity.Set<Explosion>(...);
entity.Set<Position>(...);
});
creationBuffer.Playback(); // Must happen after a queries on the mainthread.
or this...
var buffer = new ModificationBuffer(world, 1024);
world.ParallelQuery(in desc, (in Entity en) => {
var modifiedEntity = buffer.Modify(in en);
buffer.Set(...);
});
buffer.Playback();
1.0.16
New Features
Several new features were added in this release, especially gameplay relevant features to ease development.
Exclusive Queries
With the previous query API you could not target exclusive entity architectures.
This now has changed.
var exclusiveGroup = new[] { typeof(Transform), typeof(Rotation) };
var query = new QueryDescription { Exclusive = exclusiveGroup }; // Only targets entities with EXACTLY those components.
world.Query(in query, (in Entity en) => {}); // Only queries entities with "Transform" and "Rotation", no entities with other components.
Huge thanks to @MindSwipe for the contribution of the exclusive queries ! :)
Command Buffers
Due to the iteration mechanism it was not possible to the world or the entity itself during queries. Now theres a way for exactly those purposes, called "Buffers". They "buffer" operations to play them back after a query.
There 4 specialised buffers, one for each operation :
CreationBuffer
- A buffer which records creation commandsModificationBuffer
- A Buffer which records set operationsStructuralBuffer
- A buffer which records structural operationsDestructionBuffer
- A buffer which records destroy operations
A small example :
var creationBuffer = new CreationBuffer(world, 1024); <- Initial capacity, not total capacity
world.ParallelQuery(in desc, (in Entity en) => {
var entity = creationBuffer.Create(group);
entity.Set<Explosion>(...);
entity.Set<Position>(...);
});
creationBuffer.Playback(); // Must happen after a queries on the mainthread.
They are all thread safe and can be used with parallel queries.
More Parallel methods
The parallel queries were extended by a few methods like...
world.ParallelQuery(in desc, (in Entity en ) => {});
...
1.0.15
New Features
Lots of new generic overloads for world
, Chunk
, Archetype
and Entity
. To ease the development for the enduser and to operate on entities more efficient by batching calls.
All of the types above received .Has<T0...T9>
, .Get<T0...T9>
, .Set<T0...T9>
, .Add<T0...T9>
and .Remove<T0...T9>
methods. The world also received world.Create<T0...T9>
as an alternative to the world.Create(Type[])
call.
Using generic overloads instead of multiple single calls is way more efficient and faster.
var entity = world.Create(archetype);
entity.Set(new Transform());
entity.Set(new Movement());
ref var t = ref entity.Get<Transform>();
ref var m = ref entity.Get<Movement>();
becomes
var entity = world.Create(new Transform(), new Movement());
var refs = entity.Get<Transform, Movement>();
1.0.14
1.0.13
Changes & new Features
- Structural changes ( Add, Remove Components )
Type[]
arrays are now mappd to their specificArchetype
by a unique hash- Due to that unique hash the component order does not matter anymore
Transform, Rotation
&Rotation, Transform
are handled the same World
now features all entity related methods andEntityExtensions
just forward them for easier API usage.World
,Archetype
,Chunk
are now divded into partial classes/structs by features to give a better overview.- Added test for structural changes in
WorldTest
andArchetypeTest
Structural changes
Structural changes move entities from one to another archetype. It is used to remove and add components to entities during runtime.
This should never happen during a query.
world.Add<T>(in entity, new T());
world.Remove<T>(in entity);
entity.Add<T>(new T());
entity.Remove<T>();