beyond-all-reason / beyond-all-reason/RecoilEngine
Unit Componentization through ECS
- Dominant language
- C++
- Stars
- 679
- Forks
- 290
- Avg merge
- 3d 2h
- Merged PRs (30d)
- 40
Description
The idea with this task is to provide a place to discuss the componentization of unit, so currently implemented mechanisms can be better combined, or disabled. Also, currently the engine uses `entt` as an ecs backend mainly (or only?) for pathing.
Also, whether ECS or a different entity system, or just stick to CEG can be discussed here.
The alternative could be components integrated into unit `Update` and `SlowUpdate` through immediate events. ECS generally requires events to be asynchronous. I think this is where CEG comes from, see for example https://github.com/tomvandig/eccg, but have no idea tbh :D
Currently the Unit system has a very tight integration of subsystems, where (mostly) everything gets interleaved inside `unit->Update` and `unit->SlowUpdate`.
Also, it depends on a very inflexible class hierarchy that doesn't allow creating arbitrary combinations easily, as such, there are these immediate problems:
- Metal extractor has to be a subclass of building
- Builder behaviours have to be a subclass of movable unit.
Also, other "integrated" behaviours like Transport, Command and Resource management are tightly embedded in the Unit class and subclasses.
The main problem I see with this, is ECS is supposed to be data only components, and then subsystems are supposed to be working on them in tight loops. This means, to decouple from `unit->Update` and `unit->SlowUpdate`, we will likely need to move when things happen, for example (just an example, not a proposal):
- resourceProductionSystem->Update()
- unit->Update()
- unit->SlowUpdate()
- metalExtractorSystem->Update()
- reclaimSystem->Update()
- terraformSystem->Update()
- repairSystem->Update()
- buildSystem->Update()
This will mean things would happen in a different order.
So, would be really good to hear what people think and try to come up with a plan or a goal, about how to move forward.
We can write pros/cons of each approach:
- ECS:
- pros:
- very efficient looping
- high decoupling leading to more flexibility
- cons:
- likely will be somethat backwards incompatible
- requires a big refactor
- CEG: Entity components without systems, or just light systems (integrated into Update and SlowUpdate)
- pros:
- could maintain 100% backwards compatibility
- a bit less refactoring
- cons:
- not very efficient in the end
- also requires big refactoring
There will be more pros/cons, and this can be updated as they come up, this is just an initial (barebones) list.
I think there might be a way forward providing some backwards compatibility, by first laying groundwork by creating entity classes more tightly integrated into the unit graph, and then creating a sybsystem that can take over through a flag, later the flag could be deprecated and finally end with a more pure ECS.
See for example https://github.com/beyond-all-reason/RecoilEngine/pull/2283 as an example of groundwork that introduces components for extractor behaviours but doesn't really change current logic ordering and doesn't really have a System in charge. A subsequent PR to that one could move all logic processing to a System loop, thus becoming "pure".
Contributor guide
Research direction
Start by reading the Unit Update and SlowUpdate flow and the extractor-component groundwork in PR 2283. Review how entt is currently used for pathing and compare the ECS and CEG options described here. Done means reaching an agreed migration plan and goal; this issue does not define a bounded implementation or acceptance test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- game-dev
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100