Hacker News new | ask | show | jobs
by strictfp 1179 days ago
I'm working with an ECS at $dayjob. But I'm starting to question one aspect of them. Composition of functionality makes sense. And systems acting independently and only on objects with related components makes sense.

But dynamically updating the set of components for an entity in order to "send it" to some other system, and relying on the ECS as a query database to coordinate all this, seems like questionable practice to me. I'm seeing more and more of that in our systems.

I think ECSes are becoming too dynamic, and will start to eat perf, and hide relations. Like some message bus.

Anyone else with the same gut feeling?

7 comments

I really love ECS. I’ve shipped games with my own spaghetti mess of classes and poorly thought out inheritance (at least it feels that way) but ECS and composition just is much nicer for incrementally adding functionality without thinking about the big picture too much. I love that I can think about just one small feature I want to add instead of the overall grand design.

This might be bad design (no idea) but I’m working on an item system for a game right now. I have Item and ItemHolder components. If it’s a player, they’ll have an InputController component, which lets them use the Item in the ItemHolder, otherwise there is an AIController component that let’s an NPC use the item.

I have a system for handling every piece of functionality that can be defined in its smallest form, which makes it incredibly easy to add or remove functionality to any entity.

Also, performance is great. I have the mindset to not prematurely worry about performance until profiling now.

There's a few things really:

Inter-entity/system communication without a bunch of tooling to support it is always going to be a bit cludgy and hard to follow as it's by necessity dynamic at runtime. It is really useful though so writing tooling for it is a good idea.

Perf impact could be pretty big if your ECS uses archetypes and needs to do a lot of copying data around as components are added and removed. But in my experience these sort of events tend to be low frequency so probably not terrible. Always good to measure though!

Don't feel hide bound to stick within the confines of the ECS setup. It's a tool not a way of life! Straight forward message passing might be much cleaner and clearer or there might be a better data sharing strategy that can live outside the ECS itself. All frameworks provide fun puzzles of how to fit functionality into them when going round them is sometimes simpler and clearer!

If I understood correctly, you are referring to applying some sort of tag component to a set of entity to be able to query it in a separate system. Am I correct? For cross system data flow, I think a mechanism similar to what Bevy does is the way to go. A specific event bus where the developer can send any type of struct, which can also allow passing a set of entity ids. I have briefly used it for my project and I think it's clear to reason about. The only catch is that you need to be careful about timing (the time between sending and receiving an event might take one frame to propagate).

https://bevy-cheatbook.github.io/programming/events.html

That's my understanding as well.

IMO it would be interesting to consider all static components, i.e. you don't add/remove components at runtime.

If you do want "tags", have a TagsComponent (statically added to all entities that can have tags) and modify the values in it.

When working on game, the control flow must be as easy as possible to follow and modify.

With the ECS implementation in Unity DOTS, this is absolutely not the case, the control flow is mostly managed behind the scene, and multi-threaded, the simplest things are transformed into a puzzle of cascading interactions.

This is not the obviously simplest solution but can the control flow be extracted from the ECS model to be visualised separately somehow?
I think that ECS can work and be relatively simple, if controlled from the game loop and not by a "magical" black box.
> But dynamically updating the set of components for an entity in order to "send it" to some other system, and relying on the ECS as a query database to coordinate all this, seems like questionable practice to me.

Indeed it is. The idea of components is to decouple systems. Where systems generally operate on few components, and own a disjoint set of components. It is not a communication channel, just like any other database should not (primarily) be used as a communication channel.

You can combine an ECS with any number of different patterns to make your communication work: events, agents, messagebus, you name it.

Apart from memory layout benefits, I always felt ECS is a bit like giving dynamic language capabilities to a statically typed language.
Interesting. Do you have any alternative approach in mind?