Some ES design questions

So this basically states that you shall not duplicate the same function. Propagation (I named mine propulsion) controls all positions, Decay (mine is named TTL) controls death, etc. But creation can be anywhere it is needed, right? If so, good news for me, my existing structure kinda follows that (except how hierarchy is organized as was discussed above - which I’ll reorganize to see how it goes… thanks again!

Exactly else it would restrict you unnaturally.

Side note: I would just forget about hierarchy in components the way you know from OO, you just artificially restrict your self. You also will see that later on your existing systems will make magically things happen you couldn’t even dream by now. Just add a specific component to an entity, if the system for that component already exist you can enhance something with a capability, which would lead in OO to a refactor open end party, with literally one line of code! If you mix OO ideas (hierarchy is something like that) with your ES you will end in deep shit pretty soon…

It’s not even necessarily duplicating. You shouldn’t, for example, have two different systems modifying the position of an entity. (creation doesn’t count) It’s usually a sign that there is a missing system somewhere.

The classic example is damage. It’s quite tempting to have one system adjust the hitpoints when it runs into a wall, another system adjust hitpoints when standing in fire, and another system adjust hitpoints when you take an arrow to the knee. But that would be way wrong. Which one wins?

A lot of times it helps to think of systems running in parallel instead of in sequence. (There are often specific use-cases for requiring things to run in sequence but heavy reliance on that is a sign of a problem, too.) In parallel, you’d have all of those systems stomping on each other for damage.

Furthermore, if you decided to add shields then you have to go touch a bunch of code to implement that. And then you forget to modify the arrow-to-the-knee system and players complain that their shields don’t prevent them from retiring to Whiterun.

Better to have all of those damaging systems create a Damage entity. This is an Entity that links to the damaged entity and holds a Damage component. (It might also hold other stuff like decay for persistent damage like napalm… whatever.) There is a damage system that’s only job is to watch for entities with a Damage component and apply damage using whatever damage applying logic there is. Maybe it’s subtract shield value… then hp -= damage. Maybe it’s just hp -= damage.

And note: that system just does it once per frame. So if the damage entity has a decay set to 30 seconds then the player will keep getting damage per simulation frame for 30 seconds. Useful for things like napalm or being on fire in general… or even poison.

And you have a nice “damage entity” that you can tag all kinds of stuff to like damage type, sounds, whatever. It’s an entity. As you can see, there are already like 5 or 6 generic systems touched on here that don’t care one whit about each other but suddenly you can create a large variety of complex objects just by giving them the proper components.

3 Likes

If no decay is set on a damage entity, does the damage system remove the damage entity once it has applied the damage? Decay isn’t reliable in that sense - since you may have lag and the entity is removed once to late or once to early depending on sequence of execution between the systems. How do you see this?

No, there should be no lag. A decay of zero should always end up removing the decay ‘next frame’.

I highly recommend stepping your simulation time in consistent discrete steps regardless of actual ‘frame rate’ of your simulation. Your entire life becomes much easier.

that’s why my TTL system is named so - it counts milliseconds, not frames, so works more or less same way unless fps go to something really unplayable anyway. But if what’s mentioned is a sudden network lag of, say, couple of seconds - that’s a whole other story of what systems to resemble on client side and how to circumvent such cases…

Decay or TTL are server-side components. Not sure how that affects client side at all. The client is effectively just the view in this case.