Jump to content

  • Log In with Google      Sign In   
  • Create Account


Data only components


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
8 replies to this topic

#1 RobMaddison   Members   -  Reputation: 636

Like
0Likes
Like

Posted 14 April 2013 - 05:09 AM

I know this topic is talked about a lot and that, in some ways, makes it more difficult to find information on specifics so apologies if this is going over old/recent ground again.

So what is the thinking behind components only having data and no, or very limited, functionality?

In a few posts I've read that mention it, I haven't really seen a compelling reason as to why. If they don't have any functionality then where should it be? Component type 'systems'? What are they, are they 'singletons' with an 'Update' method that goes through a vector of registered components?

I appreciate there's no real right or wrong way, I would just prefer to understand the thinking behind this approach.

Sponsor:

#2 Juliean   GDNet+   -  Reputation: 2206

Like
0Likes
Like

Posted 14 April 2013 - 05:43 AM

So what is the thinking behind components only having data and no, or very limited, functionality?

 

The reason is this: Components should be generic, re-usable, non-use-case specifiy data containers. It should not matter whether a transform component is attached to the player, an enemy, a terrain, a static object, ... (which, lets face it, will matter if we give components some sort of functionality). Components should not care to which type of entity they are attached. Plus, this way we could use use components for "tagging" certain entities, e.g. via a "vunerable" component (bad example, would probably be an own "State" component, just didn't come up with something better).

 

If they don't have any functionality then where should it be? Component type 'systems'? What are they, are they 'singletons' with an 'Update' method that goes through a vector of registered components?

 

Yes, this would be indeed handled by systems. A system, while not necessarily singleton, has an update method, and goes through components - I wouldn't go as far as to say "registered", its just like:

 

void PhsyicsSynSystem::Update(EntityManager& manager)
{
entityVector vEntities;
manager.GetEntitiesByComponents<Transform, PhysicsBody>(&vEntities);
for(auto entity: vEntities)
{
//do sync of transform with physics object here
}
}

 

That way, a system will access all entities with given components it might need - without registration, without limitation. See how we use components to "identify" entities here - everything with a transform and a physics body is obviously going to get synced, no matter what other components are being attached to it. If we detach the "PhysicsBody" component from an entity, it gets left out by this system, without any other precautions.

 

Thats the main advantage of this method: its completely modular. Components don't depend on other components, entities don't depend on certain components, systems do only depend on other systems in a limited way (you might want to do physics sync before rendering update, e.g.). We form the entities by giving it certain components, and implement functionality by using systems - no huge dependency between those.



#3 RobMaddison   Members   -  Reputation: 636

Like
0Likes
Like

Posted 14 April 2013 - 06:26 AM

Thanks for the great explanation

#4 RobMaddison   Members   -  Reputation: 636

Like
0Likes
Like

Posted 14 April 2013 - 07:09 AM

I've just thought of a use case - in the non-data only CE system, imagine you have a number of camera entities in a game, each with their own camera component. For some strange reason, you want to change one of the cameras from perspective to orthogonal. In a non-data only CE system, you might have a couple of methods in the camera component which are something like:

SetOrthogonal(width, height, nearZ, farZ);
SetPerspective(fov, aspect, nearZ, farZ);

Each of these then sets the view projection matrix of the camera according to the relevant view.

In this style, from anywhere, you can call:

cameraComponentOfSomeEntity->SetOrthogonal(...);

Whereas with the 'systems' approach, you'd need to do this (I'm guessing):

cameraSystem->SetOrthogonal(theCameraComponent, the other parameters);

Is that right? If I want to call a method that changes data on a component through some functionality, it all goes through the system/manager?

#5 Juliean   GDNet+   -  Reputation: 2206

Like
0Likes
Like

Posted 14 April 2013 - 07:33 AM

Is that right? If I want to call a method that changes data on a component through some functionality, it all goes through the system/manager?

 

No, of course not. You might just as well store a pointer/reference to a certain entity/component somewhere. E.g. in my level editor, I store a pointer to the currently selected entity in my attribute window, so I can manipulate the data correctly. Systems are only there to act on ALL entities of a certain component combination. You might as well give the component a SetOrthogonal/SetPerspective method, if it aids you, but you could just as well handle this externally. I suppose we are talking about a level-editor kind of thing? Because I can't really see a valid use case in an actual game where you might want to change one camera from perspective from orthogonal...?



#6 RobMaddison   Members   -  Reputation: 636

Like
0Likes
Like

Posted 14 April 2013 - 08:26 AM

So you change the data on your chosen entity via the attribute window, what do you then do? If you change some data that needs to be processed in some way, how do you instruct the relevant system to do it.

I used the camera purely as an example only, perhaps it would be more realistic if you want to change the fov of a particular camera - the projection matrix shouldn't really change frame on frame unless something drastic like that happens (for sense of speed, etc). So you wouldn't calculate the projection matrix every frame based on the fov (picking up any changes made to the attribute) as it would be too costly. You'd need some flag to say it needs updating.

Do u see where I'm going?

Another example would be movement, the entity will have a world matrix which is used frequently for rendering, in order to calculate the matrix, the entity will also have an x, y and z position. You wouldn't recreate the world matrix from the x, y and z vector every frame as this would be too costly based on the fact that some entities may barely move much.

So let's say the entity does move by 5 in the x direction, how would you 'inform' the movement system that it or something needs to rebuild the world matrix?

#7 Juliean   GDNet+   -  Reputation: 2206

Like
0Likes
Like

Posted 14 April 2013 - 09:31 AM

So you change the data on your chosen entity via the attribute window, what do you then do? If you change some data that needs to be processed in some way, how do you instruct the relevant system to do it.

 

You might do it via a flag - I gave my "Actor" component a bDirty-flag,and the ModelSystem changes pointer to material and mesh based on the Actor data if this flag is set true. You could also use a messaging system - emit a  "XYZchanged" message, which the corresponding systems translates and act upon.

 

There is so many possiblities, it doesn't even mean you have to have a position component - you could have a translation component where everything is already stored in the matrix with some getter/setter, unless you need rotation you can set and get the position and scaling from the matrix trivially...



#8 phiwer   Members   -  Reputation: 133

Like
0Likes
Like

Posted 14 April 2013 - 01:08 PM

I was about to start my own topic when I found this thread. Sorry if I hijack the topic slightly for my own questions regarding components. Hopefully my follow-up questions will shed some more light on certain aspect of components.

 

I'm developing a turn-based strategy game using a component based game engine and have been wondering how to structure my components.

 

There are quite a lot of collection components in my game. E.g. an Army contains many units. Is it suitable to have an ArmyComponent containing many UnitCpmponents? Is that a suitable level of abstraction for a component?

 

Another thing I've been considering is the level of abstraction for the buildings I'll have in the game and also connected properties. A player can create a farm, which produces food. A player can also create a barrack to construct units, but this building also increases the offense points of troops by 10%. These types of properties can obviously change (although not likely that any other building than a farm will produce food), and as such this should be customizable easily. My question is what level of abstraction the components should be? Should there be a BuildingComponent, ProductionComponent, and ResourceComponent? Or should there be a FarmComponent, ProductionComponent and FoodComponent? Am I making my components too granular?

 

I obviously want to create a flexible system, but I don't want to over engineer either. Most buildings will be static, while their properties will change. That's why I'd like to hear your opinion of how you'd structure these relationships using a component based engine.

 

One more thing, and this question is about sub systems. I intend on making the sub systems handle the logic, and only have the components store data. Does anyone have some tips & tricks regarding how to think about sub systems? I've read that one should aim for a 1:1 relationship between components/sub systems, I am not sure this would be the case for me given my current setup with regards to my granularity of my components.



#9 RobMaddison   Members   -  Reputation: 636

Like
0Likes
Like

Posted 14 April 2013 - 03:00 PM

So you change the data on your chosen entity via the attribute window, what do you then do? If you change some data that needs to be processed in some way, how do you instruct the relevant system to do it.

 

You might do it via a flag - I gave my "Actor" component a bDirty-flag,and the ModelSystem changes pointer to material and mesh based on the Actor data if this flag is set true. You could also use a messaging system - emit a  "XYZchanged" message, which the corresponding systems translates and act upon.

 

There is so many possiblities, it doesn't even mean you have to have a position component - you could have a translation component where everything is already stored in the matrix with some getter/setter, unless you need rotation you can set and get the position and scaling from the matrix trivially...

 

Ok, thanks, I can see how that would work.  I'm just doing a bit of refactoring and I have another quick question...

 

For my camera component, I have moved all the functionality out and into my CameraSystem class.  When I iterate though all my camera objects (this is probably a bad example as there will generally be only one), it feels like I have to pass the camera component object around to any methods in my Camera System class, e.g.:

 

I have added a cameraChanged attribute and (using my previous example) when the camera 'lens' changes in the setter (SetFOV, for example), I set the cameraChanged attribute to true.  Then, in the Update method in the CameraSystem class, I iterate through the affected entities (in this case, just my one camera).  Once I have an entity to update, I first check to see if the cameraChanged flag is set and call a Reset() method.

 

The problem is, all methods in my CameraSystem class, that affect a component, will need to have the entity (or component) passed to them which doesn't feel right.  Is this generally how it works?






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS