ECS design : Persisting blueprint entities?

Hi JME community :slight_smile:

I have an ES related design question. Going to describe it with an example (as always).
In my mmorpg game that I am working on it, I have an Ability (Skill) System lets you create your abilities out of components. Take this combat skill as an example : FireBall magical attack
It consists of a Rune component (fire) and a Shape component (ball) and a few modifier components like Damage, Duration, CoolDown, Size, …

I want to let players to create and name their abilities in game. In FireBall example, we define the ability and save it in our Abilities list. Now when ever in combat we want to do a fire ball attack we can simply hit key 1 (for example) on keyboard and AbilitySystem will create a FireBall attack entity out of the blueprint, player has defined previously.

Zay-ES has a nice built in capability to save entities with PersistentComponent in database with automatically creating component tables in database. So to say, with this way I can save player abilities blueprint with Zay-ES but it will also save all the ability entities when they are used by player. For example in combat every time player do (create) a FireBall attack entity, it is going to be persisted in database while I really do not need it to be persisted because it is going to be eliminated by Decay system anyway. So is this really meaningful ? Can this lead to any unpleasant performance related issues in large scales ? (In a rough combat scene where players are doing enormous attacks)

So I need advices from pro guys here. @pspeed :slight_smile:

Often we must beware of simple conveniences that are technically breaking a design (sometimes without realizing it).

In this case, you have things that represent something that will be created and the things that are actually created. You’ve used the same class for both (convenience) even though they are not at all the same things.

So, if you want to continue treating them as the same thing then you will have to take the good with the bad. Either side will necessarily inherit all of the features/properties of the other… in this case, your non-persistent runtime components become persistent.

Alternately, you could decide that keeping both of these objects represented by the same class means that you cannot use default persistence and must choose something else to save them.

Or you could be more pure to your design and use different classes to represent the two different object types. The down side here is some duplication. The benefits are manifold, though: you don’t have these bleeding-of-features problems, you can more easily restrict what can/can’t be ‘templated’, you don’t accidentally use one thing when you mean another.

It’s up to you do decide the trade-offs.

It could even be that a component template does not need a 1:1 correlation to the things it creates. After all, those could be broken down into types and properties on some template entity… though you’ve really only moved the duplication somewhere else in that case.

1 Like

It could even be that a component template does not need a 1:1 correlation to the things it creates. After all, those could be broken down into types and properties on some template entity… though you’ve really only moved the duplication somewhere else in that case.

Got it… Yep, agree with you. Will take this approach.

That convenience deceived me at first place. As you mentioned they can be different classes that have not 1:1 relation. Previously I was not considering this fact.
Thanks for brightening up my mind :wink:

I think programmers tend to be lazy by nature… it’s what motivates us to make clever optimizations, etc…

But sometimes we get too clever for our own good and automatically short-circuit some things that really require a second look.

3 Likes