How to use EntitySystems with spatials?


#1

Hello dear community,

I would like to use an EntitySystem in my next game. I read about how they work and I decided to just give it a try.

I want my models to have one certain attribute: the EntityType (e.g. Torch, Stone, Player, …). I would add this as user data to the spatial. In order to illustrate how I would organize the whole thing I made the following picture in Paint ^^

EntityType is an enum which contains all types of entites with their (default) components and also defines the specific control which has to be a subclass of EntityControl.

Now, let’s assume I have a scene with some models (e.g. several torches laying on the ground).

When the game world is loaded the scenegraph is searched through for spatials with an EntityType attribute. For those an the specific control is added which in turn adds a real Entity object.

A torch for example would have a FireComponent which holds a boolean “isOn”. Depending on this value the TorchControl would activate / deactivate a particle effect.

Is this approach good or bad, and why?

Best regards
Domenic


#2

Respectfully, you seem to have completely missed the point of entity systems.

The whole idea of an “EntityType” is completely opposite of what an ECS is all about. The “type” of an entity is 10000000% defined by its components. Any mental idea we have of an “entity type” is just that… an idea. Something a developer may use when talking to other developers… maybe one factory method somewhere at best.

I suggest strongly that you reread the documentation and look at the existing examples.

You’ll know you have it right when you are wondering if you’d ever have a use for custom controls at all. (I rarely, if ever, use custom controls… and when I do it’s usually just a crutch to adapt something from JME.)

In case you missed the docs/examples links, here are some:
https://jmonkeyengine.github.io/wiki/jme3/contributions/entitysystem.html

AsteroidPanic is the simplest example:

For a more complicated example with networking, you can also check out sim-eth-es:


#3

@pspeed Thanks for the quick answer. Okay, I am going to read the documentation again and look at the examples.

But how do I get the connection between the model and the entity object? For example when I design a scene in the scene composer, I can’t add entities but actual models, so I later have to build a connection between model and entity object, or not?


#4

First, remember that only game objects are entities. The couch in the corner may not be a game object if the player never interacts with it, it never moves, etc… it’s just part of the scenery.

Second, you can place empty nodes and give them user data to set their entity ID or some other value to indicate their “type”… but note this is just a developer crutch. You don’t have 9 classes of weird controllers and stuff managing all that. You have one method at scene load time that goes through and fixes things up. And in this case, “type” would just be a load-time mnemonic for a set of predefined components.

I think most ES games probably don’t use the scene editor to place their game objects. But it’s certainly doable. The few I know that did used empty nodes with a user data value on them.


#5

Alright!

That’s exactly how I meant this above!

Okay, this part is different from my approach. So I assume the model is loaded when the game is initialized. But in order to design a scene it would be “cool” to be able to see the model (you can interact with) and place it how it looks best. So I would have to place it first to see how it looks and then have to remove all subnodes / geometries of that model node. Right?


#6

You don’t have to. You could have your entities be essentially visual-component free other than some indicator that they are visible at all.


#7

Okay, but in terms of designing a scene I would be helpful, wouldn’t it?


#8

Isn’t that what I’m saying?

Place your couch, your table, your chair, whatever… tag them with some entity info. Fix them up to entities when you load your scene. Done. Don’t load couches, tables, chairs at runtime at all.


#9

Ups, yeah, I got it :blush: THANKS !
I misunderstood your post earlier.


To come back to the example wih the torch: Now I would create an Entity with a Position, Rotation component. Let’s say the player picks up the torch and goes to a fire to fire the torch … In this moment a ParticleEffect component is added to the Entity. Somewhere else in the Code is a ParticleEffectAppState which cares about entities with Position and ParticleEffect components and will then add a particle effect for the torch or removes when the component is removed. Do I think right?


#10

There might be another problem in regards of the particle effect: The origin of the model / Entity is the bottom of the torch. But particles should be emitted at the top of the torch. So there is an offset needed. How would I implement this best? One approach would be to add an attribute called offset to the ParticleEffect component but this doesn’t fell “clean”. I also could create a subnode at the top of the torch and would create a separate Entity with a ParticleEffect component, but this also doesn’t feel right, since we are talking about the same game object here (a torch in this case).

Any suggestions?


#11

You could simply not have a ParticleEffect component and simply have the torch spatial know when it is on and off and animate accordingly. Whether that’s packaged with the spatial or part of some visual system that understands animations for torches is a detail.

A particle effect is not a game object. It’s a purely visual thing. The fact that the torch is lit is a game object state. It’s up to the visual systems to react to that… whether it means turning on a flame effect at the tip of the torch, turning on a light bulb, or creating a magically glowing swirly orb in some magic lantern… the game object doesn’t really care.


#12

How would I tell the spatial that the torch “is on fire”? Would the spatial have a control added which has “onFire” as an attribute which activates / deactivates the particle effect depending on the value?


#13

I am hooking into the thread since I have exactly the same question.
Paul said that he is rarely using controls so I also wonder how the transition light on -> visuals are updated is made.

I made it using an EntityContainers addObject/updateObject which seems the right direction since you update Spatials based on the GameObject.

On the other hand that implies creating a container for any possible Component. Until now I had a generic ParticleComponent as well which could represent anything. Does one loose that flexibility?

Btw: I would not add a Position and a Rotation Component but a TransformComponent (Translation, Rotation, Scale), where you could even use jme’s Transform internally.
I built a system which allows you to relate entities (e.g. the fire would be a child of the torch, just like in jme), however I discourage you doing it. It is messy, doesn’t 100% work as it should and most of the time you only need such relations for visuals, which shouldn’t be part of the Entity System (see above^^)


#14

That is one way. There are dozens of ways.

It could be a system that watches for entities with the on/off component and the model type and has a giant switch/case statement. It could be it loads separate classes by name in a registry. It could be it launches a script.

A control is in closer keeping with “this is just a kind of animation” than other things. If you were already loading your spatials/models with code instead of placing them in the scene editor then it might seem clearer to have the flame setup in code also. In your case, it just depends.

That’s sort of outside the realm of the ES… it’s just a visual reaction to some component… like so many other things.


#15

I think the basic concept is just that you try to completly separate your game logic from any kind of visualization stuff. The Entity doesn’t give a **** how it looks in the scenery.

But of course very often you want (and need) a connection between entity and spatial. But for that I could write a class for example a TorchManager which has a list of all entities and the associated spatial and of cause an EntitySet. When something changes you notice that (via EntitySet) and can react. You know that you work with torches, so you can call spatial.getControl(TorchControl.class).isOnFire(true); The control does the rest for you.

That’s how I would do it. I think I am getting closer understanding the whole thing.


#16

This right here is the key.

The only way I could see modeling the fire of a torch as an entity is if there are regularly things on fire in your game… like “fire” itself is a game object.

Else, I see a lit torch as no different than the idle animation of a character.


#17

Alright, I think I am ready to go now! :smile:

As always, Mr. @pspeed thanks for your time and effort! :+1:


#18

Before you do that, take a look at SiO2’s EntityContainer, which does exactly that for you.

The downside however is that in it’s basic form you should construct a Spatial out of the entity.
In your case you would need what I have: You call ModelContainer’s getObject() so you get the Entitys Node and can add something to that.

That however leads to another problem: What if the Model System hasn’t been run yet? Or vice-versa: If the node has been removed but you didn’t remove the control yet (less problematic). I implemented something like a reference counter on the models and they are only released when the counter is zero.


#19

This sounds somehow difficult and like it would lead to more (unneccessary) problems. I just had a look at the examples again and the same approach as I mentioned above is used there as well. There is no need for an EntityContainer, as I see things at the moment. But I also have to say, that I haven’t used ZayEs yet. I just wanted to make sure I understood the concepts and connections to the actual game world (scene) before I start coding anything.


#20

https://github.com/jMonkeyEngine-Contributions/zay-es/blob/master/examples/AsteroidPanic/src/panic/ModelState.java this is like extends EntityContainer<Spatial>.

But you are right, it’s not mentioned anywhere in the examples. I wonder how I discovered it back then.
Anyway I am talking about this: https://github.com/Simsilica/SiO2/blob/master/src/main/java/com/simsilica/es/EntityContainer.java
It’s basically exactly what you wanted to implement but hides the complexity. You just override addObject, updateObject and removeObject.

What sounds difficult is a systematic problem though: In Order for your TorchSystem to run, the ModelSystem needs to be run first. What happens if you have three systems: Model, XYZ, Torch. When you add a Torch in the System XYZ you have the described problematic. But maybe I am really overcomplicating things