Jump to content
  • Advertisement
Sign in to follow this  
HexDump

What's the point of having subsistems take care of components in a entity component sytem?

This topic is 2716 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi!,

Too much reading again, implementation, reading, trying, reading, etc... this days about entity component systems (conclusion: nothing is right or wrong :) ). I have seen people that uses "systems" to store components, update them, etc... What's the point (advantages) of doing things this way, when you can just have an entity being the container of all components it needs and updating them after a world update?.

The systems thing has also a disavantage that is that you end with a lot of diffrent systems just because you need differents componets, I think they match 1:1, what seems pretty dirty to me. Could anyone enlight here?.

Last but not hte least important, how do you ussually communicate components in an entity? My conclusion is that it is best to use a mix of Dependency injection and some kind of "event" communication for less produced evnets, but not sure. For example I have seen lot of people making Dependency injection between RenderComponent and PhysicComponent, but, what about if you don't have physics, and it is just the logic the one that moves the entity?.

Thanks in advance, and sorry to bring this talk again.
HexDump.

Share this post


Link to post
Share on other sites
Advertisement
I've not long switched over to component based entities so what I say may not be 100% accurate. So far I like and prefer it, I noticed I was using processes to "tie" things together (such as getting a missiles sound source to stay with its position) so it was a very logical change for me.

As far as dependancies go I've let each component know about its parent (I've an OnJoin method wich takes a pointer to a ComponentContainer). The component can then ask its parent for any other types of component it may need to function.

For example, most entities have a physical component and a graphical component. I;ve got a huge split between graphics(and sound)/logic so all the graphics bit does is asks the parent for a physical component and OnUpdate gets the positions and sends messages to update models etc. Providing they have the same interface I can then have a variety of physical type components (I'm using PhysX so I have basic actors and then a controller type for my player). without changing anything.

For the player I then have a controller type component which listens for events (move forward, shoot etc) and controlls all the other components accordingly. I have a weapon component that lets an entity use weapons etc. Providing I add components int he right order it works fine (I;ve not come accross any circular dependancies yet). If a component needs to recieve events (most don't so I don't want to add it as part of the component) then i make a private class to that component which has the ability to control its parent (the component) .

but, what about if you don't have physics, and it is just the logic the one that moves the entity?.[/quote]

For this I would make a purely logical component that deals with position (and say its a physical type). My graphical component would then just discover it as if it were any other type of physical component.

I like the idea of components discovering other components.

I do have entities with OnUpdate functions and same for components. If you have other subsystems deal with that logic then it would split data/logic quite well, I can see that being useful for a few things (saving being one).

Share this post


Link to post
Share on other sites
hi!,

Well I was trying to get rid of this dependency order when adding components, it is something I do not like. Anyway my system right now works more ore less like yours. My components can access parent to do things with other components. If I don't find a needed component, then I just assert.

By the way, about the systems question. How would it work? Does the system play a factory role for the type of component and Then when updating the world, systems register to OnUpdate, and update all their components? Or should own coponents the one that know what system they belong to and register automatically in its constructor or init method? Some insight would be apreciated.

In the other hand I don't quite yet see the advantages of having a system/components design over the entity(comp container)/components.

Thanks in advance,
HexDump.

Share this post


Link to post
Share on other sites
For me, sub system can process the special information that hard to do in entity/component.
For example, update order. In one entity, different components need different update order.
Render component needs to be updated in z order (for 2D game), while a motion component needs to be updated in parent/child order (scene graph order if any). It's only a simple example.
It's hard to let entity or component to handle that.


The systems thing has also a disavantage that is that you end with a lot of diffrent systems just because you need differents componets, I think they match 1:1, what seems pretty dirty to me. Could anyone enlight here?.


True. But the sub system function is not duplicated with component.
There are two kinds of method to split the functions between sub system and component,
1, Sub system only processes special information (such as update order) and component does the real logic (move, render). In this case, sub system should be quite simple and more like a container while component is complex.
2, Component only holds data, no code, no logic, sub system handles all logic. This is pure data driven and may be useful for high performance games.
I prefer 1 unless performance is a problem (such as if you are developing COD or Halo).

Share this post


Link to post
Share on other sites

By the way, about the systems question. How would it work? Does the system play a factory role for the type of component and Then when updating the world, systems register to OnUpdate, and update all their components? Or should own coponents the one that know what system they belong to and register automatically in its constructor or init method? Some insight would be apreciated.

In the other hand I don't quite yet see the advantages of having a system/components design over the entity(comp container)/components.

First off, I'm going to mention T-Machine if you haven't read it.

Next, the benifit is fairly simple: systems update components as a coherent group. This makes things very fast. Your objective is to collect everything related in one place both in memory and in code. And, they aren't completely orthogonal. You could have your entity store pointers to components in the systems.

See, when you have a Component Manager, the manager is handling all the code and memory to a component. The manager will have a contiguous array of components to manage, this keeps your updates fast, because you aren't jumping around memory to get at your data. The manager also handles all the update code for your components, so you get really tight loops over all the data. Lastly, the managers know what type of component they are working on, thus if you build components from a base IComponent class, you need less common virtual functions in the base.

Now, you can break things up even more, since many of your managers should be able to avoid talking to other managers. This means you can write sections of each manager that are 100% thread safe, allowing you to thread-by-manager ( if you know that each component is isolated, your managers could launch more threads to take care of batches of components ). And I say sections, because you will inevitably have components that require a "pre-run" "threaded run" and "post-run" sections to allow them to sync to other managers without needing locks. And, it should also be obvious that some managers must run before other managers (or you have to accept multiple frame delays in data propagation). If you were to update by entity, then you'd have a harder time threading everything since who knows what components each entity has, and some won't be thread safe. You'd also loop over your entities more times, as you scatter-gather of stuff to update for each stage of your update loop.

And you wouldn't really "register OnUpdate". The update order would be fairly concrete. Something like:

PlayerManager->Update();

WeaponsManager->UpdateParallel(); // launches some jobs to our thread pool
ItemsManager->UpdateParallel();
WaitParallel(); // waits for ALL parallel jobs that may be outstanding.
AnimationManager->UpdateParallel();
WaitParallel();
PhysicsManager->Update();

AttachedObjectManager()->Update();

ParticleManager->UpdateParallel();
SoundManager->UpdateParallel();
WaitParallel();
RenderManager->UpdateParallel();
WaitParallel();
RenderManager->Render();


edit:
Some other random thoughts. On the PS3, this is important because a SPU thread can only do so much. You want to limit your code to as tight a loop as you can, and then hand it a lot of the same type of data over and over again. Thus, something like updating animations works well on a SPU. You write a tight loop to update the bone matricies, and then pull in every single animation component one at a time and chew through its data (hopefully the manager sorted them too so common data like the base skeleton can stay on the SPU longer). On any other platform, that exact thought process gives you large speed boosts because your making better use of each core's cache.

Share this post


Link to post
Share on other sites
Hi!,

Thanks a lot for the answers. Some doubts/disagrees though.

First of all, it is correct that having systems you can run through a bunch of homogeneus components, that being kept continuos in memory cache pretty well. Didn't think about it. Just not thinking about performance right now :).

On the onther hand there's something that I don't get. Who is responsible of holding and running systems in correct order? Couldn't this lead to a bad mantainable system? I mean, everytime you add a new component, you have to add a new system (not allways but almost everytime), then you have to go to the place subsystems are kept, find whre in code it should be called, and and the update call there. Perhaps when registering a system a priority can be provided to avoid this.

Last question, how a script system could fit here. I mean, I don't plan being able to create components using scripts (lua in my case). Components are C++ things that a lua script can assemble to create an entity protoype if needed (registering it with the C++ side) or have this prototype hardcoded in C++ (just an entity class). So, If I want an animation component that does his things in script, would I have a base Animation component, and then 2 deriving ones StaticAnimationComp and ScriptableAnimationComp and just one System holding both types?.

Thanks in advance,
HexDump.

Share this post


Link to post
Share on other sites
If your static and scripted animations provide the same function, they are the same component.
Then you only have only one AnimationComponent. In it, you have a basic object called animationImpl, and use different implementation.
This is a little like two level component systems but simpler.

If your static and scripted animations are like, but with difference. Extract the same part to a component and make difference as two different components. This part should be complex and heavily depend on the design. We can't take a simple example here.

For you update order of sub system question, yes, a update priority will help much, just a integer is enough.

Share this post


Link to post
Share on other sites
Hi!,

If your static and scripted animations provide the same function, they are the same component.
Then you only have only one AnimationComponent. In it, you have a basic object called animationImpl, and use different implementation.
This is a little like two level component systems but simpler.


Do you mean something like a decorator pattern? Same interface to the outside, and redirect method calls to containing implmentation? Good point.

On the other hand would be the World class a good place to manage the systems (registration, update, etc...), or it would be better to send them to a higher level, for example the Old good "Game" class?


I have just read the T-Machine article. Quite inspiring. The problem with all this components arquitecture, is that I miss some implementations examples. It is pretty hard to see all this things playing in the head.


For exmaple, The writter suggests an entity should be just an id to categorize related components, but where components initialization occurs? I guest entity tempaltes enter the scene now. I could have entity tempaltes that have a list of components tags (to let each subsystem know if they should link one of its components to this entity), and initialization values for this components based on entity type (don't really know how to handle/store all this data). This way when I ask the world to create a new entity, it will query the template manager, get the themplate and pass it to all systems to let them create the type of component they handle if needed. What do you think?

Deletion of entity is another problem (related to speed). If I have say 50 systems, when I delete an entity I should call 50 removeEntity callbacks in my ssytems with the entity id to let them delete everything. On the other hand we could inspect its tempalte class get the component tag list and call just that systems, but don't you think it is too much work for just a deletion? Wouldn't it be better to just have a class with a list of components, or the systems handling its components? this way it will be fairly direct, having X calls though (one per system).

Another thing that is bugging me is how to handle dependencies. Each system should know what type of component it manages, and so its dependencies, so it could ask dependent systems to create components based in the entity template it received at first. But this, do not enforces too much coupling between systems?


All feedback will be greatly apreciated.

Thanks in advance,
HexDump.

Share this post


Link to post
Share on other sites

On the onther hand there's something that I don't get. Who is responsible of holding and running systems in correct order? Couldn't this lead to a bad mantainable system? I mean, everytime you add a new component, you have to add a new system (not allways but almost everytime), then you have to go to the place subsystems are kept, find whre in code it should be called, and and the update call there. Perhaps when registering a system a priority can be provided to avoid this.

Part of your main loop would be responsible for calling all system related functions (ie, like i posted above). A priority idea might work, but I'd argue is even less maintainable as you need to know all other priorities inorder to guess at the priority of your new component. If you really want to avoid the update order problem (and a class of threading problems), double buffer your component state. Every component would then gather information from the "this frame" buffer, and only write information into the "next frame" buffer. You then swap the two buffer pointers at the end of the update, and repeat the process.


Last question, how a script system could fit here. I mean, I don't plan being able to create components using scripts (lua in my case). Components are C++ things that a lua script can assemble to create an entity protoype if needed (registering it with the C++ side) or have this prototype hardcoded in C++ (just an entity class). So, If I want an animation component that does his things in script, would I have a base Animation component, and then 2 deriving ones StaticAnimationComp and ScriptableAnimationComp and just one System holding both types?.
[/quote]
One route to take is have all components issue messages on interesting events. Other components can then register listeners for those events. You'd have your animation component and a LuaScriptComponent. Part of your lua script setup would say what other components you are interested in for this script so it can connect listeners. Then, as your animations fire off events it reports them to the script component. You could then reuse the same LuaScriptComponent to attach to physics events or user input events all based on the script it is running.


I have just read the T-Machine article. Quite inspiring. The problem with all this components arquitecture, is that I miss some implementations examples. It is pretty hard to see all this things playing in the head.

For exmaple, The writter suggests an entity should be just an id to categorize related components, but where components initialization occurs? I guest entity tempaltes enter the scene now. I could have entity tempaltes that have a list of components tags (to let each subsystem know if they should link one of its components to this entity), and initialization values for this components based on entity type (don't really know how to handle/store all this data). This way when I ask the world to create a new entity, it will query the template manager, get the themplate and pass it to all systems to let them create the type of component they handle if needed. What do you think?

Sounds about right.


Deletion of entity is another problem (related to speed). If I have say 50 systems, when I delete an entity I should call 50 removeEntity callbacks in my ssytems with the entity id to let them delete everything. On the other hand we could inspect its tempalte class get the component tag list and call just that systems, but don't you think it is too much work for just a deletion? Wouldn't it be better to just have a class with a list of components, or the systems handling its components? this way it will be fairly direct, having X calls though (one per system).
[/quote]
It wouldn't have to be 50 calls. You'd make one call to check what the type of the entitiy is and retrieve its template. You'd then call ComponentManager::Delete() for each component type listed in the template.
But the likely better way to do it is to have entities request that you delete them. Have a separate part at the end of the update loop that runs through and tells your 50 systems to delete every component that requested to be deleted. It tends to be faster to remove a whole bunch of things at once than it is one at a time. But the main reasoning is to be thread safe, as deleting in a threaded update would require locks everywhere, while setting a few flags to check after the threads finish won't require a lock. (you may want to do something similar with your create calls too).


Another thing that is bugging me is how to handle dependencies. Each system should know what type of component it manages, and so its dependencies, so it could ask dependent systems to create components based in the entity template it received at first. But this, do not enforces too much coupling between systems?
[/quote]
First, ask yourself why are your components dependent on one another? decouple as much as you can. Then, consider that if they are dependant, you should be able to order them in your template such that they get created in the correct order to work. If you can't, then separate the steps into a "create" then "init" so that you can setup enough stuff for each component at create that the init phase is ready for them to link to one another.



Didn't think about it. Just not thinking about performance right now :).
[/quote]
That's fine, I'm going to keep mentioning things as I think of them, because some patterns are easier to thread than others. If you don't follow them from the start, you've mostly eliminated the ability to thread your application. You don't have to thread it from the start, but thinking about how your design affects threading. A small game isn't likely to even really need it anyway, but still worth thinking about as threading is the future (or present really).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!