Ecsrx Versions Save

A reactive take on the ECS pattern for .net game developers

7.0.x5

1 month ago

Thanks to @thejayman for adding a fix for ComputedGroups incorrectly raising removal events for entities which were not currently being tracked internally.

6.0.x1

2 years ago

Summary

The high level information here is that we have dropped explicit releases for .Net Framework 4.6 and instead are now just focusing on building netstandard2.0, in the future we would like to move to net7 but until a lot more frameworks have migrated over to it we are just going to stick with netstandard.

We have also changed the way ObservableGroup objects work by separating out the group matching mechanism to a new interface known as an IObservableGroupTracker which will monitor the groups/entities and then relay onto the ObservableGroup when there is a change.

This diagram shows the new process, which historically all used to take place within the ObservableGroup so this makes the object simpler and allows other parts of the system to track group changes.

Other Changes

There are some breaking changes around namespaces for events changing as well as a new wrapper around component interactions on the type called IComponentAccessor, which reduce the amount of type lookups if you are doing a lot of interactions with component types.

5.1.x2

2 years ago

Summary

While this isn't a massive release it does have a few small changes in terms of how component removal is handled.

So first of all a HUGE thanks to DoctorDepthum on the discord who noticed the regression of the IDisposable handling of components within entities, this has been rectified now so components with IDisposable are now correctly disposed.

So just to clarify when you remove a component now, the underlying logic that runs in the ComponentPool will check if the pool contains reference types, and if so null out the index, and check if the component implements IDisposable and if so will trigger the disposable logic, then finally release the index for future consumption.

5.0.x1

2 years ago

Summary

The high level change for this version is that SystemsRx is now its own repository within the EcsRx org, however realistically at a high level you wont notice much difference other than a few package name changes:

  • EcsRx.Infrastructure.Ninject -> SystemsRx.Infrastructure.Ninject
  • EcsRx.ReactiveData -> SystemsRx.ReactiveData
  • EcsRx.MicroRx -> SystemsRx.MicroRx

There is also now a non EcsRx dependent SystemsRx.Plugins.Computeds which has base computed types without being dependent upon IGroup etc. The EcsRx version still exists and builds on top of this allowing you little change in terms of usage.

IEventSystem Changes

The IEventSystem now has 2 publish methods, the default one which is backwards compatible is the default Publish<T> however there is also now a PublishAsync<T> which will use IThreadHandler to Run a new task for it which by default does a Task.Run(...) for the publish.

IThreadHandler Changes

The IThreadHandler now has a Run method which allows you to just do an arbitrary run of an action via the thread handler (defaulted to Task.Run).

4.1.x2

2 years ago

Summary

Some of these changes actually happened in previous releases but a few things have been moved down into SystemsRx such as the pooling mechanisms, as they are useful regardless of the ECS aspect of things, so now they can be used without.

Also there have been some changes thanks to @Fijo which makes it easier to include IObservableGroup objects on the fly in your systems via attributes by using the GroupBinding plugin.

GroupBinding Plugin

This is optional but if you do want to include multiple IObservableGroup objects within your systems (such as IManualSystem) you can do so like this:

[FromComponents(typeof (LevelComponent))] public IObservableGroup LevelAccessor;     
[FromComponents(typeof(EnemyComponent))]  public IObservableGroup EnemyAccessor;

Which is directly lifted from the Roguelike2d Repository which has some real life usages of this plugin and how it can simplify the system and reduce dev time/boilerplate, there are some other approaches where you can use FromGroup to pass in an explicit group or just use FromGroup without a group on systems which implement IGroupedSystem, and it will take the default group property as its argument.

This also simplifies those usecases for people who were originally using IManualSystems before they got moved to SystemsRx and were left without a simple way to resolve an IObservableGroup when needed.

4.0.x1

2 years ago

Summary

Currently a lot of the EcsRx features are not directly tied to the ECS paradigm but as they are part of core they come bundled together.

Part of this change is to decouple some of that so there can be a SystemsRx library which has no notion of EcsRx which can be used by people who want to have nice infrastructure and DI abstractions, as well as nice simple systems to run logic in a simple way, but don't want to have to worry about using entities and components.

SystemsRx

So this split has now made it so the new library acts as a layer underneath EcsRx and provides basic System Execution, Infrastructure, DI and common extensions as well as a couple of simple systems such as IManualSystem and event handling systems, it even supports plugins without needing to worry about the EcsRx layer.

EcsRx

At the high level EcsRx hasn't changed much, its just a lot of the core innards have been moved down a layer (and this is mentioned more on front page readme), there are a couple of breaking changes (mentioned in breaking changes document), but for the most part you continue to use the library as you do right now.

Under the hood to use EcsRx you will be pulling in SystemsRx but this simplifies things a bit and also lets you run systems outside of the ECS paradigm alongside your ECS related ones, so its best of both worlds.

3.12.x2

3 years ago

Batching Plugin + Structs

As the issue with structs and batches still seemed to have no real avenue to being resolved other than only allowing blittable types, the decision has been made to just make this a requirement.

If you do not use the batching plugin then your structs (if you use them) can be of any type you want, but if you want to get the performance boost of them all being batched together you need to use blittable types otherwise they cannot be pinned.

Also updated group builder

Added a couple of struct methods to the group builder, this should allow you to use the builder to make groups with struct types in too

3.10.x

4 years ago

Persistence Plugin

The major thing to talk about is the new persistence plugin which adds the ability to save your entities to and from files (or anywhere else you want), out the box it supports saving and loading from binary files, but there is an example project for how to change that to JSON if you prefer it to be human readable/editable.

As the persistence functionality is built on top of Persistity you can also make use of pipelines for your own needs, like extracting certain data from your game state and persisting it as a save game file, or even sending off metrics to PlayFab etc.

For more info on this look at the example projects and persistity documentation, or feel free to discuss in the discord server.

DI Improvements

There are some new helpers for DI around custom functions on activation as well as being able to specify that your binding should only be used when injecting into a certain type or set of types.

3.9.x

4 years ago

As part of the previous update we moved the IObservableScheduler into the core, but on top of this we have streamlined what it does, so its now IUpdateScheduler and also implements ITimeTracker which allows you to get the elapse/total time in a cross platform way.

This would be a minor update but as it breaks the surface API it needs to be a major release.

3.8.x

4 years ago

This isn't a huge update but there are lots of words explaining whats happened :D

IObservableScheduler now in core

This was originally brought in as a way to have a streamlined cross platform "EveryUpdate" style notion, as every engine/framework does their update loop differently, so this exposed a way for those events to be fed through in a sane-ish way. So in Unity it may be from a UniRx Observable.EveryUpdate in MonoGame it may be from a Game.Update while in a console app it may just be a timer ticking at 60fps.

The point is that this allows plugins to have systems which update according to the host platform but be agnostic of it, so plugin systems no longer need to worry about having platform dependent observables, as historically if you wanted to have a cross platform system your only option really was an IManualSystem and make some update loop yourself which is not great.

And off the back of this a new basic system has been introduced which wraps up the underlying update mechanism and exposes a simple processing point.

New IBasicSystem

This is basically a cut down IReactToGroupSystem but the schedule of it is taken care of for you, as in most cases people would just have it default to every update anyway, so in these cases you can just use the normal IBasicSystem and it will work on any platform and doesnt need the ReactiveSystems plugin.

This as mentioned above makes plugin development easier as you can at least have a cross platform system without needing other plugins or writing any of your own boilerplate code.

IGroup and Group are more in line

This isn't a massive update, but the gist is that IGroup and Group have not been on the same page for a while, as IGroup just exposed component lists to match on, whereas the Group implementation had that AND predicates built in.

In most cases predicates are the exception, and while they allow you some great flexibility it needs to be more separated, so there is now a GroupWithPredicate which is basically the same as the old Group class, and the new Group class just contains component lookups.

For the most part this wont effect most people, as the helpers/builders have been updated to automatically create the appropriate class for you, however if you had your own classes inherit off Group and you used predicates in them, you may need to now inherit from GroupWithPredicate.