Sign in to follow this  
M4573R

Fast ways to get components

Recommended Posts

M4573R    144
It seems like when objects get split into many components like size, position, scale, model, etc. Systems like graphics need to access all of these per-object, per frame. I'd be nice if this operation was as fast as possible. The fastest I can think of is to have an enumeration value for each component type and just index directly into an array. However as a game expands, I could see having 100+ component types. This makes things like using entities for particles very unrealistic because each particle would have 400 bytes of pointers sitting around mostly unused. The most common approach is to only store the components you want and search linearly. This leads me to my question, which would be the fastest realistic way to access components in an entity: map and string identifier, map and int identifier, set and int identifier, sparse vector with int identifier, etc.

Share this post


Link to post
Share on other sites
Hodgman    51344
Firstly, components are bigger than just 'position' or 'scale' -- Individual data fields would be properties. Components actually do something useful on properties.

So the fastest way is just to put the properties into the component as member variables:
struct ModelComponent
{
Vec3 pos;
Quat rot;
float scale;
Model* gfx;
}
Then you could have a visibility system that does:
for each ModelComponent, if visibility test passes, add to visible list
And a rendering system that does:
for each item in visible list, render item

If you do want to store the properties outside of the component, you just turn the member variables into pointers.

Then you can have some kind of allocation algorithm in the system class:
struct ModelSystem
{
std::vector<Vec3> positions;
Vec3* AllocatePos();
};
struct ModelComponent
{
ModelComponent( ModelSystem& s, Model* m ) : pos(s.AllocatePos()), ...
Vec3* pos;
}

Or you can get the pointer from another component:
struct PositionComponent
{
Vec3 position;
};
struct ModelComponent
{
ModelComponent( PositionComponent& p, Model* m ) : pos(&p.position), ...
Vec3* pos;
Model* gfx;
}

Share this post


Link to post
Share on other sites
Zipster    2365
As for storing components, we give each component a unique ID and use an unordered_map for storage. Lookup is pretty fast and you're not storing NULL pointers in an array for components that don't exist. Also keep in mind that a lot of the time you can grab a component once and cache it for later use. When an object is added to the scene, the graphics system grabs all the components it needs for that object and holds on to them until the object is removed from the scene.

Share this post


Link to post
Share on other sites
M4573R    144
Caching components could get hairy if its different entities communicating. You'd have to have reference counted handles or something. I usually think of components more generally and don't separate them from properties. I use "components" for any common functionality or data that more than 1 object might have. For instance a camera would have camera logic, and would store its target and frustum data, but it's position would still be stored in the position component. In this case caching would work great, but again, between different entities would get tricky.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this