3
\$\begingroup\$

I spent a good amount of time trying to get my head around ECS but the "S" is still obscure to me - the farthest I went is that I know a System is where the magic happens; it's where behaviors get implemented, mostly.

However, most references I read about ECS were quite broad in their examples and didn't go much beyond the "Movement" and "Physics" Systems.

That said, what does a system that a decreases health look like? My domain is TypeScript, but examples/snippets in any language work just fine.

I think the above is hard for me to visualize mostly because my current understanding of ECS is quite as follows:

  • An Entity is a unique ID that represents a thing,
  • Each Entity has a "collection" of components, that describes what the Entity is composed of and are nothing but data,
  • All spawned entities are cached in memory, usually through a "World" object,
  • An Entity is given a Health component through a world.addComponent(entity, health) function call,
  • Then, to decrease the Health of this Entity I just spawned, I'd have to...? This is where things get blurry and dark for me - without the imperative thinking health.decreaseBy(10), the System just does not "click".
\$\endgroup\$
2
  • 4
    \$\begingroup\$ The answer depends on why you want to decrease the health of an entity. Do you have a game mechanic which periodically decrease health? Or do you decrease health as the result of some entity-entity interaction? In general, having a "Health" component does not necessarily imply that you need a "Health" system. There is no strict 1:1 mapping between components and systems. You would have a "Damage" system which deals with processing damage events or a "Death" system which handles entities whose health fell below zero. \$\endgroup\$
    – Philipp
    Commented Aug 26, 2022 at 7:40
  • \$\begingroup\$ @Philipp if you have time, I'd love to see this expanded into an answer. \$\endgroup\$
    – DMGregory
    Commented Aug 26, 2022 at 12:48

1 Answer 1

7
\$\begingroup\$

You're on the right track: systems are where the logic resides and where behaviors are implemented. Systems are basically functions where the arguments are components. So if you wanted to create a damage system you need:

  • A health component which will be decremented
  • A damage component which defines the amount to decrement

Then your system iterates through all entities that have both a damage and health component and decrements the health accordingly.

Once you've done that you'll most likely need some kind of death system. You can implement that either with a system that iterates through all entities that have health and checks if they are at 0 or below, or else by adding a dead component to entities with 0 health in your damage system and have your death system iterate all entities with a dead component.

Now there's lot's of ways you can implement a damage/death system in ECS, but the takeaways are that when working in ECS:

  • If you want something to happen you need to do it with a system.
  • Data exists in components, so when your systems need to do something they will get their parameters from some component (e.g. if you want a damage system that applies different damage amounts you need a damage component to store that data)
  • You want to keep systems minimal and focused on very narrow behaviors. To expand on @Philipp's comment, if you have a game that has a variety of mechanics around health (e.g. poison, elemental, healing, etc.) you should resist the urge to make one health system that handles all those cases and break those up into a variety of systems (e.g. a poison system, an elemental damage system, etc.).

NOTE: There are exceptions to the rules above but they are uncommon.

Why Make Systems Small?

@Vaillancourt asked what the rationale is for keeping "systems minimal and focused on very narrow behaviors", so here goes...

At a high level we're all idiosyncratic humans and we should use whatever suits our particular brains best, so if you find lots of files confusing, go ahead and centralize things in larger systems. At the end of the day the point is to build games with a minimum of pain and suffering.

That said ECS architecture is very aggressively tilted towards composition. It's designed with the intent that everything is broken into tiny modules that can be easily plugged together and rearranged, and that philosophy extends to systems as well as components. When first starting out with it I would advise someone to go with the grain of ECS and then start figuring out their own sweet spot for composition.

So as an example imagine we're making an RPG and I code up a health system that handles all the types of damage, healing and death - basically anything that affects health or is derived from it.

The first problem I might run into is performance: there's lots of components associated with this system and most of them won't be present on an entity at any given time (i.e. most entities won't have a heal component, or a damage component on any given frame). Many ECS implementations are optimized for concrete sets of components (e.g. anything with health AND damage) over more abstract queries (e.g anything with health AND/OR damage AND/OR heal, etc.) and there's going to be a lot of conditionals in your system to handle all the cases.

However, you shrug this off - your game simulates small parties fighting not massive battles, so the performance issues are negligible, and you keep plugging along with your full-fat health system.

However, designers being designers you start getting curve balls. First they want to add a spell that prevents damage from poison. Then they add another spell that gives your neighbors a speed boost when you take damage. Then they get weird and decide that whenever the Oneiromancer class takes damage it creates a nightmare token in their inventory. At this point your choice is either to fold half of your game into your health system - which would be madness - or just break it up into tiny little chunks. That way when a designer modifies a mechanic that intersects with health, you can either modify or add a small system, rather than going spelunking through a huge one.

I know that's an extreme example, but in my experience when I bundle up a bunch of stuff into something closed (e.g. a large function or class) I usually have to break it up into it's constituent parts further down the line.

\$\endgroup\$
4
  • \$\begingroup\$ You want to keep systems minimal and focused on very narrow behaviors. I'm not sure I see the rationale here. Sure, you don't want to put everything in the same system, but I don't see the harm into grouping similar things in the same code file. It's a delicate balance between having too many files and files that handle too many things. \$\endgroup\$
    – Vaillancourt
    Commented Aug 26, 2022 at 12:32
  • \$\begingroup\$ Thanks for the edit. \$\endgroup\$
    – Vaillancourt
    Commented Aug 26, 2022 at 15:01
  • \$\begingroup\$ Thank you for the answer, @Mattia - really insightful! It led me to think though that I may be misunderstanding ECS all this time. In order to elaborate, let's shift the use-case a little bit: instead of a Health System, let's talk about a card draw system. 'say we have a card stack - when the user clicks on it, a card is drawn. I think it's not through ECS that I issue the command "draw card", right? I mean, I see ECS more applicable to game engine elements than gameplay elements per se - am I correct? \$\endgroup\$ Commented Aug 26, 2022 at 17:02
  • 1
    \$\begingroup\$ @GuilhermeOderdenge There's nothing that says you have to use ECS for every part of your game - so in this case card logic may be better handled outside of it - but I don't think it's accurate to say that ECS is better suited for engine than gameplay code. ECS is good at giving you very modular systems that you can easily combine which is especially useful for gameplay code, since that's where you're going to have the most churn and constant change of specifications. \$\endgroup\$
    – Mattia
    Commented Aug 26, 2022 at 17:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .