Jump to content

Entity-Component Systems and performance in JavaScript.


groutxo
 Share

Recommended Posts

First of all, hello everyone. First time posting, since I started with html5 a bit ago. I'm planning an ECS on JavaScript and, because of my little experience with JS, I'm getting into a few concerns.

 

I'm new to JS, so I may be missing some JS technique that could help me to handle this. Anyway, I'm trying to keep myself informed on JS language inners, so that I can get as much power as I can from it.

 

I suppose everyone knows what an ECS is. Anyway, I'll explain at least how I understand it. An ECS is composed of Entities, Components and Systems. Components are data, entities are bags of components, and systems just operate on entity components it's interested in to apply some kind of logic. It's also well explained on this post.
 
What I currently planned for entities and components was something like this (syntax may not be the correct, but the point is just to show the idea):
var NormalShipEntity = {    positionComponent: { x: 0, y: 0 },    velocityComponent: {....},    shootComponent: { shootrate: 30, shoottype: derpl },    lifeComponent: { health: 100 },}var InnocentShipEntity = {    positionComponent....,    velocityComponent....,    lifeComponent....}

Here, I have created two kinds of entities that both are ships, but one has a shootComponent and the other doesn't, so here is the real sugar of ECS: you can create new entity models by composing them of components, and getting rid of a deep level hierarchy.

 

Now, the question is about systems, that are the real code acting on entity components. There are two main approaches when applying system functionality to entities:

  1. Iterate once over all entities and, foreach entity, check all systems against it. This checking implies to know if the system has to process this entity. For example, a MoveSystem needs positionComponent and velocityComponent: if one of them is missing, the MoveSystem doesn't act on that entity.
  2. Register each entity in a per-system list, so that each system has the entities that it has to iterate, and the check is made just once, but the iteration over a single entity will for sure be multiple if it has several systems that have to process it.

The approach I want to take is the first one. So here's some pseudocode

foreach( entity in entityList ) {   foreach( system in systemList ) {      if( system.HasToProcessEntity(entity) ) {         system.process( entity );      }   }} 

Now, my issue comes within that HasToProcessEntity method within System. The first thing I thought was to use the hasOwnProperty over all components the system needs, and if everyone succeed, then return true and process the entity with that system. I know a pretty straightforward way to make the check is with bitmasks, but there may be a better choice using JS.

 

I'm mainly concerning about performance on hasOwnProperty. Also, if anyone could throw a bit of light on how to accomplish this without using hasOwnProperty, or tell that hasOwnProperty will be just fine, would be appreciated.

 

 

Thanks in advance.

Link to comment
Share on other sites

I simply use a filter-function on my list of entities, like this:

MotionSystem = {  tick: function(entities, deltaTime) {    entities.filter(function(e) { return e.position && e.motion; }).forEach(function(entity) {      entity.position.x += entity.motion.dx * deltaTime;      entity.position.y += entity.motion.dy * deltaTime;      entity.position.rotation += entity.motion.drotation * deltaTime;    });  }};

I am not concerned about performance as of yet - if that becomes an issue at a later point then I'll handle it then :)

Link to comment
Share on other sites

Thanks for your response. I think I'm going to do something very similar to what you posted, but iterating over systems foreach entity:

Engine = {  tick: function() {    entities.forEach(function(e){      systems.forEach(function(s){ if(s.performsOver(e)) s.tick(e); })    })  }};MotionSystem = {  tick: function(entity, deltaTime){    entity.position.x....    // more  },  performsOver: function(e){    return e.position && e.motion;  }};

Could this perform worst than your approach anyhow? I may be doing something wrong, I'm noob at JS. Anyway, I've just learned a few tricks from you, thanks for that too.

 

Btw, I took a look at ld28, good job with that! I hope I'm also doing stuff early. You code everything by yourself, don't you? I've seen lots of libraries when arrived this territory (sorry for the offtopic  :rolleyes:).

Link to comment
Share on other sites

I don't know if you know Ash (an Actionscript 3 entity-system framework) - https://github.com/richardlord/Ash - but I ported it over to Javascript - https://github.com/brejep/ash-js - and it has an interesting approach to the problem you are describing. 

 

In Ash, a system gets a linked list of nodes that it can update. These have already been filtered by the engine. A node is a tick list of components that a system might need to update.

 

For example, a collision system might require references to spaceship collision nodes and bullet collision nodes, where a spaceship collision node has a reference to any entity that has a position component and a spaceship component and a bullet collision node has a reference to any entity that has a position component and a bullet component.

 

For a simple example see: https://github.com/brejep/ashjs-asteroids-example

Link to comment
Share on other sites

I'm presently using an internally developed ECS engine for my games and I'm releasing it's code.

I have another approach to identify witch entity have to be updated with witch system.

actually. an entity in my implementation is just a holder object with an ID and primitive function to add componnents to.

then I have systems (I call them modules in my implementation), each module "watch" one or more components.

when an entity adds a component, it is bound to the modules that handles this component.

in my main loop, each module have a list of only entities it should update.


an first implementation can be found here : https://github.com/Ezelia/eee

this code is a little outdated, but it has the implementation I described above

 

I just started a wiki : https://github.com/Ezelia/eee/wiki  the included demo can also help https://github.com/Ezelia/eee/tree/master/demo

also, to have fast entities loops, I use for (;;) syntaxt instead of for-in , to make this possible I implemented this HashMap https://gist.github.com/alaa-eddine/6317515 witch share properties of both JS arrays (fast loops) and JS objects (key/value access).


hope it'll help :)


 

Link to comment
Share on other sites

@brejep: aha, so you check on entity creation if that entity has the components of a node, and if it does, you attach it to the system list that wants those kind of nodes, am I understanding right? I guess that your update is done foreach system. I'll take a look at your code anyway.

 

@Ezelia: first of all, the post you made some time ago about ECS has been what encouraged me to ask here, so I'm not entirely new with your way =). So your approach is, you have Entity being just an ID and components that have the Entity ID associated. Then, on Entity creation (addition of components), you check in which modules (system) the Entity needs to be processed and add it to these modules own list. Anyway, I'll take my time to read your code and your wiki.

 

Thank you two, it's been of great help. I have not still started with my ECS because of not having time, but everytime I coded a line more in my game (that was before I started the post sadly), I couldn't stop thinking about this way of organising stuff, and more if we take into account the JS language, it seems perfect for this approach). I'm also caring about performance just because the game I'm working on, could have ~120 entities, and maybe a max creation/deletion ratio of 2 or 3 per second, so I wanted to stay sure in this.

 

Thanks again, this forum is being a big help  =)

Link to comment
Share on other sites

@groutxo : here is an article to start with http://alecmce.com/library/why-use-entity-systems-for-game-engineering, there are so many articles about ECS, but this one is short and explain in a clever way what's ECS and what's it's main differences to OOP :) hope it can help you.

btw, I have a game with around 22000 alive Entities (about 320 entities drawn each frame thank's to viewport cropping), with pretty hight deletion ratio and it works very good :)  ... 60 FPS on modern browsers, and between 30~50 FPS on mobile (depending on models)

 

the slowdown you can get, will not be because of ECS, but of other "classic" performance issues, so if you follow good practices to eliminate them, you'll get good results anyway.
 

 

EDIT:  I'm currently working on a total remake of my game "Germiz" using ECS, it'll support desktop, mobile, cocoonjs wrapper, and everything I learned from this forum to make a multi-platform HTML5 game. thank's to ECS I was able to completely separate the game layer from device adaptation layer ... after the game publication (maybe next weeks ... months depending on my time), I'll publish an article about the game structure and how ECS made some features simple, and some other more complex (or at least less natural for an OOP developer)

Link to comment
Share on other sites

@Ezelia: it's good to know about your numbers, now I know I'm not mad or anything! Waiting for your article, in the meantime I'll read that last one you posted.

 

So great, I hope I can finally go with JS again and try it (time, time, time... but anyway, a good plan before starting to re-code isn't any bad).

 

My experience with ECS was a bit bitter. I tried some test on C++ but never finished it. Now that I've tried JS and HTML5 a bit, I see how easy it can be achieved here, because of the nature of the language and the ECS itself, and this information is greatly helpful.

 

Also, I'll take a deep read to that link, as you said, there's lots of sites where you can get info about ECS, and this may be confusing (at least to me).

 

Thanks for everything, and go on with your "Germiz" remake and your whole ECS project!

 

 

P.D.: I've played Germiz for a considerable time by now, it's addictive

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...