EntitySystem: How to represent entities in the SceneGraph

Hey Monkeys,



i am currently thinking about a strategy to use an ES with JME. I think that an ES has many benefits, both in singleplayer but especially in multiplayer games. But, for the beginning, i wanted to make a very, very simple singleplayer application just in order to get some prototyping done.



For the moment, i’m using GitHub - adamgit/Entity-System-RDBMS-Beta--Java-: An Entity System of type "RDBMS Beta" (see the wiki for detailed explanation) . I will eventually roll my own implementation once i have figured some more stuff out.



Basically, what i want to achieve is the following:

Just a flat surface with some objects lying on them. Based on the properties of the objects, different interactions are possible. For the beginning, it will just be colored spheres.



So, i made some components for the different properties of the spheres:

Position (obvious)

Movement (no rolling or so, just translating along a given direction with a given speed)

Color (obvious)

Shootable (when shootable, the sphere should be “clickable” and some information is displayed on the console, nothing fancy).



So, getting things done in the ES is simple. i have a system that processes the entities and just changes position based on movement. There is the first headache: it introduces a kind of dependency bewteen the “Movement” and “position” component (movement makes no sense without position), but that is not the matter that bothers me.



The question is, how do i correctly set up the link bewteen entity system and SceneGraph? I have a central entityManager that does all the necessary stuff. e.g. creating entities, adding / removing components from an entity etc.pp.

My current idea is to add a “SpatialComponent”. This component holds a reference to a spatial in the scene graph. So, only entities with that specific component will be added to the scenegraph. This has the benefit that i could just create a System that processes entities with the spatial component and set their translation etc. pp. accordingly, and vice versa. Imagine a physical entity that is moved by physics and not by the entity system. I could simply add a system that gets the spatials current position and update the component. The only thing that has to be made sure is that there is no physcal entity with a movement component, since that would pretty much break the whole thing.



I am just wondering, since i suspect that i am not the only one who attempts to use an ES with JME: How do you handle synchronization between the scenegraph (which i think of as the ‘view’ in MVC) and the ES (which i think of as the ‘model’)? Is that whole ‘SpatialComponent’ idea a good one or is this horribly wrong from a conceptual point of view?

About SpatialComponent. I just did it like that:



[java]public final class NodeComponent {



private Node node;

private List<Geometry> mapChildMeshes = new ArrayList<Geometry>(); //Collection of meshes



public NodeComponent(Node nodeComp, Long entityID) {



node = nodeComp;

recurseNode(node, entityID);

}





public Node getGeneralNode() {

return node;

}



//Read the node child to find geomtry and stored it to the map for later access as submesh

private void recurseNode(Node node, long entID){

Node nd_temp = node;

nd_temp.setUserData(“EntityID”, entID);



for (int i = 0; i < nd_temp.getChildren().size(); i++){

if(nd_temp.getChildren().get(i) instanceof Node){

nd_temp.getChildren().get(i).setUserData(“EntityID”, entID);

recurseNode((Node) nd_temp.getChildren().get(i), entID);

}else if (nd_temp.getChildren().get(i) instanceof Geometry){

Geometry geom = (Geometry) nd_temp.getChildren().get(i);

geom.setUserData(“EntityID”, entID);

//System.out.println("omomomomoomomomo GEOMETRY ADDED : “+geom.getName()+” for Entity "+mObjectName);

mapChildMeshes.add(geom);

}

}

}



public Geometry getChildMesh(String name){

for (Geometry mc : mapChildMeshes) {

if(name.equals(mc.getName())){

return mc;

}

}

return null;

}



public List<Geometry> getChildMeshs(){

return mapChildMeshes;

}



public void destroy(){

mapChildMeshes.clear();

node.removeFromParent();

node = null;

}



}[/java]





You can get any Node/Geometry UserData “EntityID” and you will get the ID of the Entity.

I’m not very much experienced with EntitySystems but in my ES I’m doing it like you do it: I have a component Model that holds the representation. The only thing you have to make sure is, that you don’t attempt to send the whole component with the spatial when finally going to multyplayer environments^^

@enum said:The only thing you have to make sure is, that you don't attempt to send the whole component with the spatial when finally going to multyplayer environments^^

Yes, i am very well aware of that. But i don't think that will be much of an issue.

I will need to make a wrapper that saves the current state of the entity system anyways. Either to disk or, which I'd prefer at the moment, to an SQL database (currently, using HyperSQL in-process looks very promising). I will need to make sure that the spatial component is not serialized / saved in those cases anyways. So, this check will already be present when i'll go multiplayer.

Thanks for the warning anyways ;)

Just want to tell you guys that I playing with the entity system my self for a while. So far, I has some posts where I and @pspeed said our though about such a system. What I can say It’s do-able and run-able, got promising features anyone want to have with but … BUT I finally quit using it! :stuck_out_tongue:



Well, some thing I did my self to test how far I could go in that Entity System: ( the image said it all)

  1. Use Artemis
  2. Data backend use Apache Cayenne
  3. Interface use MetaWidget and Subtance LAF to get the look of Unity ( the Engine I used to play with, and have good implemented ES)
  4. Groovy for Scripting



    http://farm9.staticflickr.com/8434/7732354350_e1288b5851_c.jpg



    Getting JME and ES play together is easy, nice and promising. And love to know if any one can get make it better. Contact me, I will give you the code :stuck_out_tongue:

@atomix , did you use Artemis with 400 entities and 50 moving entities? Just for stressTest.

@polygnome said:
I will need to make a wrapper that saves the current state of the entity system anyways. Either to disk or, which I'd prefer at the moment, to an SQL database (currently, using HyperSQL in-process looks very promising). I will need to make sure that the spatial component is not serialized / saved in those cases anyways. So, this check will already be present when i'll go multiplayer.


For me it happens the other way round: I started with networking and will implement saving/loading later which indeed needs the same thoughts.
I looked at H2 embedded DB and will probably use it. I'm not a database expert so it might not be optimal^^
@mifth said:
@atomix , did you use Artemis with 400 entities and 50 moving entities? Just for stressTest.

Don't you think that is a little low for a stress test?

I just wrapped up a little test, in my ES moving around 10.000 entities takes 7-11 ms. frame rate is ugly as hell (22fps) since i simply also attached 10k geometries to the root node, which kills rendering speed.
@polygnome said:
Don't you think that is a little low for a stress test?

I just wrapped up a little test, in my ES moving around 10.000 entities takes 7-11 ms. frame rate is ugly as hell (22fps) since i simply also attached 10k geometries to the root node, which kills rendering speed.


Try to use Box meshes. like:
[java]
Box b = new Box(...);
Geometry geo = new Geometry ("xxx", b);
[/java]

Do you loop your entities in update() method every frame?
@mifth said:
@atomix , did you use Artemis with 400 entities and 50 moving entities? Just for stressTest.

I'm sure Artemis can handle around 1000 entity with *representation in 3D* which is a Render System ( our JME3). Yes they should be 1000 spatial for that 1000 entity but not alway nessesary. A lot of thing should have involve in the complete ES system working in JME3, so as I said : my attemp is just a quick and dirty run to walk through: intergrate an ES system, make UI to compose it, data backend and see the result. The bad think is now my computer can make good JME screen cast and I can't show you guys the Artemis Space game example in 3D. Cool :p
@mifth said:
Try to use Box meshes. like:
[java]
Box b = new Box(...);
Geometry geo = new Geometry (&quot;xxx&quot;, b);
[/java]

Do you loop your entities in update() method every frame?

I did something like that, this is from simpleInit():
[java]
Box b = new Box(Vector3f.ZERO, 1, 1, 1);
Geometry geom = new Geometry("Box", b);

Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Blue);
geom.setMaterial(mat);

for(int i = 0; i <= 10000; i++) {
// randomize start location
int x = random.nextInt(500);
int z = random.nextInt(500);
Vector3f position = new Vector3f(x, random.nextFloat() * 10, z);
UUID entity = em.createEntity("Entity#" + i);
em.addComponent(entity, new Movement(position.normalize().multLocal(new Vector3f(1,5,1)), random.nextFloat()));
em.addComponent(entity, new Position(position));
Spatial spat = geom.clone();
em.addComponent(entity, new SpatialConnector(spat));
rootNode.attachChild(spat);
}[/java]

And this is simpleUpdate():
[java]@Override
public void simpleUpdate(float tpf) {
super.simpleUpdate(tpf);

// long start = System.currentTimeMillis();;
entitySystem.update(tpf);
// System.out.println(System.currentTimeMillis() - start);
}[/java]

and this is the subsystem that gets called in order to move the boxes:
[java]Set<UUID> movementSet, positionSet, spatialSet;

public SpatialMovementSystem(EntityManager em) {
super(em);
movementSet = em.getAllEntitiesPossessingComponent(Movement.class);
positionSet = em.getAllEntitiesPossessingComponent(Position.class);
spatialSet = em.getAllEntitiesPossessingComponent(SpatialConnector.class);
}

public void processOneGameTick(long lastFrameTime) {
}

@Override
public void update(float delta) {
Set<UUID> temp = new HashSet<UUID>(spatialSet);
temp.retainAll(movementSet);
temp.retainAll(positionSet);

for(UUID uuid : spatialSet) {
Movement m = em.getComponent(uuid, Movement.class);
Position p = em.getComponent(uuid, Position.class);
p.position.addLocal(m.direction.mult(delta));
SpatialConnector connector = em.getComponent(uuid, SpatialConnector.class);
connector.spatial.setLocalTranslation(p.position);
}
}[/java]

I will split that system in two shortly (one for movement, one for updating the spatials position), which will eventually slow the whole thing down a little bit since iteration has to take place two times.
but maybe then there is a way to multi-thread the whole thing...

3D ViewPort has limit of geometry to 300 000 triangles (on a screen). this way is used in all cool games. if you see more than 300k triangles on a screen, so you need to optimize something.



That’s why i said 400 entities. :slight_smile:





PS. More than 400 entities on a screen is too bad either. It’s better to have 1 object with 100k triangles, than 1000 objects with 100 triangles (every object). This is GPU limitations…

That’s why GeometryBatchFactory.ortimize() and BatchNode help in merging many objects.

Yes, but what does that have to do with the performance of the entity system itself? Of course you need to optimise your 3D representation somehow, but that has nothing to do with the capabilities of your ES.

1 Like

Just a note: if you find yourself shoving system objects (like a Spatial) into an Entity component, then you are doing something wrong.



Also, what is your “movement” component and what makes you say it has a dependency on “Position”? A system may use some Movement component to update Position but the components themselves should not care about one another since Components don’t contain any logic.

@atomix I would be intterrested to take a look at your code :slight_smile:

@pspeed said:
Just a note: if you find yourself shoving system objects (like a Spatial) into an Entity component, then you are doing something wrong.


I got interested in this. Why you think like that?
@pspeed said:
Just a note: if you find yourself shoving system objects (like a Spatial) into an Entity component, then you are doing something wrong.

I agree. But currently i do not see how i can handle using JME and an ES. If i were to write my own 3D engine then ofc i could simply add a "RenderComponent" and have a subsystem that just renders all entities that have that component. But unfortunately, implementing a whole 3D engine is not an option for me.
That why i asked how others handle this. How would you do it?


Also, what is your "movement" component and what makes you say it has a dependency on "Position"? A system may use some Movement component to update Position but the components themselves should not care about one another since Components don't contain any logic.

The movement component just hold a vector3f with the direction and a float for the speed. nothing fancy. I might even just use one vector3f (unnormalized ofc).

The component itself does not care about anything. It just holds the data. nothing more. Thats why i don't particulary like the postet spatial component by @mifth above - it already contains logic.


What i mean with dependency is that in the SpatialMovementSystem that i posted above only entities can be handled that have ALL of those components present. But on a second look, a don't think that is a bad thing. I can refactor the system to split it into a movement subsystem and a system that just updates the spatials position, and everything will work fine. So basically that is a kind of very loose coupling that seems to work well.
@shirkit said:
I got interested in this. Why you think like that?


Because Components are data. Systems are systems. Systems use Components, Components do not use Systems.
@polygnome said:
I agree. But currently i do not see how i can handle using JME and an ES. If i were to write my own 3D engine then ofc i could simply add a "RenderComponent" and have a subsystem that just renders all entities that have that component. But unfortunately, implementing a whole 3D engine is not an option for me.
That why i asked how others handle this. How would you do it?


I have a general model descriptor component. It is up to the system to interpret how use this. The system that interacts with spatials finds the right mesh. A system that renders to a map might find the right icon... etc. The component doesn't need to know about a system-specific object because system-specific objects should exist in the system... since they are system-specific.

@polygnome said:
The movement component just hold a vector3f with the direction and a float for the speed. nothing fancy. I might even just use one vector3f (unnormalized ofc).

The component itself does not care about anything. It just holds the data. nothing more. Thats why i don't particulary like the postet spatial component by @mifth above - it already contains logic.


What i mean with dependency is that in the SpatialMovementSystem that i posted above only entities can be handled that have ALL of those components present. But on a second look, a don't think that is a bad thing. I can refactor the system to split it into a movement subsystem and a system that just updates the spatials position, and everything will work fine. So basically that is a kind of very loose coupling that seems to work well.


In fact, systems that require multiple components to be present is the CORE of an entity system based app. I have almost no systems that deal with only one component.

Well @pspeed , as @polygnome , I don’t see any other option. I store the Spatial so the I can play animations, change material definitions, add objects to the object’s node (healthbar). I don’t see any other option to do that besides this :confused: I thought this at the start of using Artemis in my game, and this was the best solution I could think of. It may be still wrong, but this is the “wrongless” I can thought of.