Am I following the “rules” of an entity component system?

Hello everyone. This is my first post here! I did not see a section for introductions, so if there is, please forgive me.I am really enjoying JME so far. A lot of work/talent must go in to this! Thanks for that :slight_smile:

I am relativity new to java. I have spent most of my time on web programming and such. (I also did a lot of Actionscript back in the day so java feels very friendly to me). I can’t say if I am doing this in the most efficient way or not, but if feels OK. I have a mathematics degree so the logic comes quite naturally. Anyhow, I apologize in advance if my java “lingo” is not quite up to scratch. There may be better ways to say the things I say. I am a bit neurotic, so I feel the need to explain myself all the time… so forgive me for my long-winded post too. lol.


I have been inspired by many sources to try Entity-Component Programming… I just love the idea of the whole thing. (Maybe it is my background in web development that causes this.)

I have attempted to create a simple Entity-Component setup that is compatible with JME. Right now I am just experimenting with it in a few simple ways-- no ambitious plans.

Here is what I have:

I have a MultiHashmap that holds all the initially created “entities”. The entities have uniquely generated tags. Components are set to the tags by a method that is called after the given entity’s creation (I did this so I could churn out entities with certain components in a ‘for loop’ or something). I then access this map from a game state (which acts as my system) and pull out all the entities with a given component. This is stored in it’s own Hashmap. The state manipulates this Hashmap through whatever logic it possesses.

My questions are:

1: If i was clear enough in my description-- is this following the “rules” of an entity component system?

2: How does one incorporate models without breaking the rules? Right now I have a simple ‘position’ system that generates cubes for the position entities. The cubes are moved around by the position values being updated. There is still only data in my position components, and models are handled by the position system. Is this OK? Are models usually incorporated in the position system? What I did works, but I’m not sure if it is the ‘proper’ solution. What i did felt very “sloppy”. I am hopeful that I have not just found a complicated way to do OOP haha.

I can’t sleep at night because I am trying to wrap my head around this.

Going out for a walk to think!

-J

There could be a system that moves the models based on changes to the position components. E.g. a simple Control or Appstate would do. Generally it sounds like you gotthe concepts right.

1 Like
@normen said: There could be a system that moves the models based on changes to the position components. E.g. a simple Control or Appstate would do.

Aha! so that is fine!I was thinking about doing that.

It is much more clean than what I have now. And the model state would not modify the component so it does not break the rules… wow so simple. I must have had a brain fart when I threw that idea aside. It happen to me when I start thinking of a new thing for too long.

I will proceed with that and am hopeful that it gives me some new ideas/understanding of the way ECSs work. Putting this in to practice seems to be the only way to fully grasp it.

I am now having visions of “model types” as a component too. Not sure how its going to work yet but I feel like the idea will surface in my brain soon.

Thanks for the help and nice to meet you :slight_smile:

Yes generally it sounds correct, a lot of complexity only comes if you try to make it multi-threaded, a single threaded es does not contain much magic.

Well your position system is somewhat similar to my ingamesystem, it basically based on the data in the entity creates a visualization, and then keeps it in sync with the entity’s state. So no events observers or any other higher logic is involved, basically its only a loop that applies all values.

1 Like
@Empire Phoenix said: Yes generally it sounds correct, a lot of complexity only comes if you try to make it multi-threaded, a single threaded es does not contain much magic.

Well your position system is somewhat similar to my ingamesystem, it basically based on the data in the entity creates a visualization, and then keeps it in sync with the entity’s state. So no events observers or any other higher logic is involved, basically its only a loop that applies all values.

Actually threading is simpler with an ES if you do it right… You automatically have a threadsafe communication set up.

@Empire Phoenix said: Yes generally it sounds correct, a lot of complexity only comes if you try to make it multi-threaded, a single threaded es does not contain much magic.

Well your position system is somewhat similar to my ingamesystem, it basically based on the data in the entity creates a visualization, and then keeps it in sync with the entity’s state. So no events observers or any other higher logic is involved, basically its only a loop that applies all values.

Good it is nice to hear that I am on (or close to) the right track. <3 :slight_smile:

@normen said: Actually threading is simpler with an ES if you do it right.. You automatically have a threadsafe communication set up.
True that, making the ES threadsafe is the harder part, the rest is really easy then.

So just running it separate update() loops is not going to be optimal is it? I think I will have some reading to do tonight about threading. From what I know now though, it isn’t that much more complex is it?

Isn’t it just, in laymen’s terms, “do this”, like I have now, but in a separate thread?

Edit: And shouldn’t it be safe, so long as I stick closely to the “rules”? like if 2 things don’t modify the same thing?

Well let me give a few examples, you have a gun system and a player system
if the gun now spawns a new bullet(entity) when should the player system be able to see it? This needs to be clean

If two systems acces the same component in different threads (wich potentially run on different cpus) you might get cache locality problems, if you do have no synchronizing logic involved.

Then you don’t want to use use synchronized directly, as it will force synchronize all cpu caches, not only the ones affected.

Basically ConcurrentHashMap and immutable components are your friend for most problems that might arise.

(Well and then you can do the overkill as i do, let each physicspace have a seperate thread, and fork join them from the physicsystem)

But in short, this is still way more easyer than with a traditional OO approach,
also depending on the game you might not necessarly need a multithreaded ES, as this increases the work, and if not necessary will provide nothing to the end user.

1 Like

Only one system should update the content of a component. If you have multiple systems updating one component you either need more components or more entities.

@normen said: Only one system should update the content of a component. If you have multiple systems updating one component you either need more components or more entities.

True, the caching problem applies to reading to however.

Yes that makes a lot of sense Empire P.

But maybe for now I will first just concentrate on a single threaded ES now, just to get a handle on how to deal with the simple problems. Then after I get the hang of it I will use some of these lovely hints that you have given me when i revamp my system :slight_smile: Its all just a learning thing for now.

ConcurrentHashMap should be useful in the near future. I think you both have saved me some future headaches by bringing this up!! my newbie factor would have caused me to take days to come to this conclusion with synchronizing and such.

Thanks!!!

Note: I encourage everyone learning entity systems to try to write their own so that they understand the issues and how it kind of fits together. However, once you have kind of a handle on that idea then you may want to go ahead and try an off-the-shelf JME-ready solution like Zay-ES.

http://hub.jmonkeyengine.org/forum/board/projects/zay-es/

It handles a bunch of stuff for you (including persistence and networking if you end up needing it) and deals in advance with a bunch of issues that you haven’t encountered yet. There are even two sample games that show usage.

1 Like
@pspeed said: Note: I encourage everyone learning entity systems to try to write their own so that they understand the issues and how it kind of fits together. However, once you have kind of a handle on that idea then you may want to go ahead and try an off-the-shelf JME-ready solution like Zay-ES.

http://hub.jmonkeyengine.org/forum/board/projects/zay-es/

It handles a bunch of stuff for you (including persistence and networking if you end up needing it) and deals in advance with a bunch of issues that you haven’t encountered yet. There are even two sample games that show usage.

Wonderful! thanks. I will probably do exactly as you say. That is actually the only way my brain is able to learn about someone else’s work. I can only relate if i have done something similar… even if it is just a super simple version. (mine is REAAALY simple)

I have been reading about multithreading for the last hour and I think it might be worth it to use someone else’s ES just for that fact… not to mention the potential nightmare of networking (which i doubt I’ll need, but who knows). As for persistence i had some ideas… they were probably really bad ideas…

Anyhow I am reading the Zay-ES documentation now. I will probably pop over to the Zay-ES section soon ask some questions :D.

Good day to everyone!

As suggested above I played around with Zay-ES. I like it a lot. I made two spinning entity cubes! and did a few random mathy things to some components. I got a few errors with the log4j thing… I am sure it is something I did way wrong. I’ll worry about that in the future though :slight_smile: I will for sure use it when my project hits the brick wall of complexity. But I feel like I have more to learn about the basics first. So I am back to my ES.

I was thinking of playing around with some more complicated stuff with my ES so I am going to go for multithreading! I don’t mind doing the extra work. this may be a perfect opportunity to learn about the basics of the subject.

I have been reading up on it a lot and I think i can handle it. I am just not sure when/where to fit it in.

Edit: Never mind. I give up for now. my mind is exploding. I think I’m too newbie. I’m going to stick with pspeed’s solution hehe.

@Jarky said: Edit: Never mind. I give up for now. my mind is exploding. I think I'm too newbie. I'm going to stick with pspeed's solution hehe.

:slight_smile:

Yeah, multithreading is tricky and getting performance good in a multithreaded ES is also tricky.

Multithreading in an ES is pretty much a case where a ‘system’ will have its own thread and simply (continuously) iterate over its entities of interest at some rate. This is not much different than how Monkey Trap or my Asteroids clone examples do it except those do all systems in one thread. But those systems don’t care if they get split off into another thread, really.

1 Like
@pspeed said: :)

Yeah, multithreading is tricky and getting performance good in a multithreaded ES is also tricky.

Multithreading in an ES is pretty much a case where a ‘system’ will have its own thread and simply (continuously) iterate over its entities of interest at some rate. This is not much different than how Monkey Trap or my Asteroids clone examples do it except those do all systems in one thread. But those systems don’t care if they get split off into another thread, really.

So theoretically, if I were to make all my data thread-safe, like with ConcurrentHashMap and also had immutable components (as mentioned before) , it would be possible to tie in multithreading?

I did try this in my basic ES. I ran some code on another thread which accessed my data. My testing only extended to println’ing a few things to confirm that it was actually doing what I hoped…There were probably some unforeseen conflicts but…

Is my thinking overly simplified? Or is the complexity all in the optimization?

I feel i have an OK grasp on multithreading(but still learning). My problem is figuring out where it is best to let it happen.

So you’re saying, with Zay-ES that if you involve multithreading, you let it handle a whole system? So let all systems run on the main thread except for the complex/time consuming ones?

But those systems don't care if they get split off into another thread, really.

So when you say this, you mean Zay-ES is completely safe to use multithreading, given that one knows what they are doing when they implement it?

I doubt I’ll need it any time soon, but this is becoming a very good learning experience for me, so I feel as though I should keep playing with this (even though did become frustrated with my brain yesterday hehe).

@Jarky said: So theoretically, if I were to make all my data thread-safe, like with ConcurrentHashMap and also had immutable components (as mentioned before) , it would be possible to tie in multithreading?

I did try this in my basic ES. I ran some code on another thread which accessed my data. My testing only extended to println’ing a few things to confirm that it was actually doing what I hoped…There were probably some unforeseen conflicts but…

Is my thinking overly simplified? Or is the complexity all in the optimization?

I feel i have an OK grasp on multithreading(but still learning). My problem is figuring out where it is best to let it happen.

So you’re saying, with Zay-ES that if you involve multithreading, you let it handle a whole system? So let all systems run on the main thread except for the complex/time consuming ones?

So when you say this, you mean Zay-ES is completely safe to use multithreading, given that one knows what they are doing when they implement it?

I doubt I’ll need it any time soon, but this is becoming a very good learning experience for me, so I feel as though I should keep playing with this (even though did become frustrated with my brain yesterday hehe).

Blindly using ConcurrentHashMap really isn’t enough because now you will have a problem of inconsistent state.

The code that handles the threading and updates in Zay-ES is the trickiest part. It has also been described elsewhere in nauseating detail so I won’t regurgitate here.

The long and the short of it, each EntitySet is its own view of the entities. If you follow the rule that components are immutable (and only swapped out when changes) then each EntitySet is a fixed snapshot in time until applyChanges() is called which updates the contained entities to the latest view. This can be thought of as reissuing the entity set query but it’s actually way way faster than that because of internal optimizations.

But conceptually, that’s a way to think about it.

In a true ES based application, in theory the ‘systems’ could even be run on a giant federated server farm with each system on its own machine. Zay-ES doesn’t support this case (though it was designed to) but you can think of it that way.

You could in theory run every ‘system’ in its own thread… I wouldn’t. But you could. It’s helpful to think of it that way because as you break out your components and such you should be thinking about “what if these were happening in parallel” because sometimes it leads to cleaner design. Sometimes not.

Monkey Trap, for example, takes good advantage of the fact that it knows that one ‘system’s’ update loop has completed before another. Altering those systems to run in parallel might have side effects.

1 Like

Well using a safe datastructure is around 90% of the complexity.

Then (not i speak not for zay es, but for my own es)
I basically have a barrier, that once per tick all systems intrested in doing this tick sync at a specific point in time.
At this point all entity removals additionas or changes take effect. And it starts again.
-> This means you have a perfect System isolation, a slow ticking system will not see it’s data change while it is working on it, instead it is using a snapshot taken at the system start.

By having this two things, a clean determined logic that ensures that even using multithreading I have a completly determined outcome and using threadsave structures (mich mostly boil down to immutables and ConcurrentHashmaps)

1 Like
@pspeed said: Blindly using ConcurrentHashMap really isn't enough because now you will have a problem of inconsistent state.

The code that handles the threading and updates in Zay-ES is the trickiest part. It has also been described elsewhere in nauseating detail so I won’t regurgitate here.

The long and the short of it, each EntitySet is its own view of the entities. If you follow the rule that components are immutable (and only swapped out when changes) then each EntitySet is a fixed snapshot in time until applyChanges() is called which updates the contained entities to the latest view. This can be thought of as reissuing the entity set query but it’s actually way way faster than that because of internal optimizations.

But conceptually, that’s a way to think about it.

I’ve reached a point where I realize a method, similar to applyChanges, would have to be added to my simple ES. Like you say could not blindly set components and read from another thread. I would have to make sure everything had one controlled point. Am I thinking of this correctly?

In a true ES based application, in theory the 'systems' could even be run on a giant federated server farm with each system on its own machine. Zay-ES doesn't support this case (though it was designed to) but you can think of it that way.

You could in theory run every ‘system’ in its own thread… I wouldn’t. But you could. It’s helpful to think of it that way because as you break out your components and such you should be thinking about “what if these were happening in parallel” because sometimes it leads to cleaner design. Sometimes not.

Monkey Trap, for example, takes good advantage of the fact that it knows that one ‘system’s’ update loop has completed before another. Altering those systems to run in parallel might have side effects.

That is very helpful!