Component Based Objects?

Anything and everything that's related to OGRE or the wider graphics field that doesn't fit into the other forums.
Post Reply
User avatar
oddrose
Orc
Posts: 470
Joined: Thu Feb 15, 2007 2:08 pm
Location: Gothenburg, Sweden
Contact:

Post by oddrose »

it sounds like you mean that this saves you time? or am I wrong? I mean, the bad thing about hard-coding it is that you may have to re-code it. And then you save time with flixibility?
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Post by KungFooMasta »

It means you can create your objects in real time if you wanted to, by adding and removing components. Your object design/functionality is not determined at compile time, but based off the components it has. It's more editor and script friendly, promotes designing GameObjects piece by piece, and allows for any combination of components.
Creator of QuickGUI!
User avatar
oddrose
Orc
Posts: 470
Joined: Thu Feb 15, 2007 2:08 pm
Location: Gothenburg, Sweden
Contact:

Post by oddrose »

yeah, I totally agree with that (how could you not?) but that's not what I asked about. But nevermind the question, I don't think it has a real answer. Thanks though.
User avatar
TheN00B
Gnoblar
Posts: 24
Joined: Fri Aug 31, 2007 5:41 am
Location: Portland, OR, USA
Contact:

Post by TheN00B »

Ran into this thread, and thought I'd share my thoughts. I originally read about this type of object management in the Game Programming Gems 5 text, although I don't remember the author or the chapter title off the top of my head. I have employed an object management system similar to what you are all speaking of, so I thought I'd share. My system is fairly static, and I'm know of several areas that could be improved upon.

In this system the only thing that identifies an object is an ID (which is a hash value). There is no actual object class, struct or otherwise as I had difficulty separating object purpose from component purpose. Each component inherits from an IComponent virtual class, as well as an interface. The interface declares the functionality of the component type (i.e. Physical component would have an add force method), and the IComponent virtual class declares the functionality of a component (such as creation, serialization etc...).

Interfaces are identified by an interface ID, and components are identified by a component ID. In my current implementation these are enum values, but this approach wouldn't be too hard to change.

All my components are "stored" in a database, which in my implementation is a struct. This database comprises of three peices of data and looks like the following:

Code: Select all

	struct SObjectManagerDB
	{
		//////////////////////////////////////////////////////////////////
		// Static component type data
		SComponentTypeInfo					mComponentTypeInfo[NUM_COMPONENT_TYPE_IDS];
		std::set<EComponentTypeID>			mInterfaceTypeToComponentTypes[NUM_INTERFACE_IDS];
		
		//////////////////////////////////////////////////////////////////
		// Dynamic component data
		std::map<CObjectID, IComponent*>	mComponentTypeToComponentMap[NUM_COMPONENT_TYPE_IDS];
	};
The first peice of information is an array of the struct SComponentTypeInfo which contains a function pointer to the creation method, a function pointer to the destruction method, and a hash value for the component (for identification). The struct looks like this:

Code: Select all

struct SComponentTypeInfo
	{
		ComponentCreationMethod     mCreationMethod;
		ComponentDestructionMethod  mDestructionMethod;
		CHash                       mTypeHash;
	};
The second piece of information is a set of components that are of a certain interface type (an array of sets).

The last piece of information is another array that matches the interface type to a map keyed by the object ID (which is a hash) that contains a component.

The components I implemented all read data from an XML file, which I realize isn't the best solution, but at the moment is the easiest. I can then create an object editor, or even a world editor, that can change objects by adding and removing components, or changing the properties of a component.

My system also has iterators that aid in controlling the data, as well as an object manager class that aids in querying the database, and controlling components. The biggest thing missing at this point is a messaging system, but I am working on an event manager that is separate from the object system.

I am certainly a noob (I mean look at my name :P), but I thought I'd share my method of managing components.

Cheers!

P.S. Please do criticize, I certainly could use it :)
There is a message in my alphabits, it says Ooooooooooooooo...
User avatar
steven
Gnoll
Posts: 657
Joined: Mon Feb 28, 2005 1:53 pm
Location: Australia - Canberra (ex - Switzerland - Geneva)
Contact:

Post by steven »

@TheN00B: Interesting solution.

One point bothers me: if you want to access the Physical component of an object you need to search in all the map and use RTTI to identify if a physical component exist. Isn't this expensive?

Also how do you add/remove objects? Are you obliged to lock the map (with a read-write mutex)? Or did you achieve to separate the creation/destruction phase from the read phase so that you don't need a lock?
User avatar
TheN00B
Gnoblar
Posts: 24
Joined: Fri Aug 31, 2007 5:41 am
Location: Portland, OR, USA
Contact:

Post by TheN00B »

@steven: You are correct that searching through the map is an expensive process, which makes it a less then suitable data structure. However for my implementation objects are controlled by reacting to events, so thus far it hasn't been an issue.

I am not saying that using those data structures is a great solution, just something I have temporarily created.

Creation, destruction, and component access is controlled by the object manager class, which employs a read-write mutex on the database. My game currently has three separate threads, one which is controlled by CEGUI, so really only two threads that access this system. Thus far I have had no problems with data corruption.


Thanks very much for the thoughts, I guess other then component communication, access time is a major flaw of this system. I may have to re-think some things to correct this issue.
There is a message in my alphabits, it says Ooooooooooooooo...
Dom
Halfling
Posts: 57
Joined: Wed Jul 14, 2004 10:12 am
Location: Berlin

Post by Dom »

Component based systems help with the inheritance problem, especially when the "design" needs to be tweak-able. Moreover - as said - you can compose/prototype new entities in the run-time.

Something I am heading for it to have lists for certain types of components. Thus the physics manager/service/server has a list of all 'active' physics objects - adding objects or removing objects will alter that list. This removes the need for the search.
Unfortunately not all ogre classes have a user data member that can be used as bi-directional link i.e. for 'tagging' materials or physics objects - so you need to have additional look-up tables for that you can ask "Has this entity a physics tag?"
User avatar
eugen
OGRE Expert User
OGRE Expert User
Posts: 1422
Joined: Sat May 22, 2004 5:28 am
Location: Bucharest
x 8
Contact:

Post by eugen »

U can always add a data member to the classes that doesnt have it and submit the patch
User avatar
volca
Gnome
Posts: 393
Joined: Thu Dec 08, 2005 9:57 pm
x 1
Contact:

Post by volca »

Dom wrote:Component based systems help with the inheritance problem, especially when the "design" needs to be tweak-able. Moreover - as said - you can compose/prototype new entities in the run-time.

Something I am heading for it to have lists for certain types of components. Thus the physics manager/service/server has a list of all 'active' physics objects - adding objects or removing objects will alter that list. This removes the need for the search.
Unfortunately not all ogre classes have a user data member that can be used as bi-directional link i.e. for 'tagging' materials or physics objects - so you need to have additional look-up tables for that you can ask "Has this entity a physics tag?"
I agree with you, this can be implemented with the component(property) listeners.

I think you should not need the reverse lookup (under certain conditions that is).
You'd only need it if you used scene queries or such. If the entities are only slaves to your code, and you do all the engine related tasks yourself (including collision detection, etc), then the data member should not be needed at all.

The archetype approach should help with the rapid prototyping (pseudocode):

Code: Select all

archetype physical {
   property physics {
     collision_type bounce
   }
}

archetype ambient_sound_source {
   property sound {
      ambient_sound 'default.wav'
      mode loop
   }
}

object bug : physical, ambient_sound_source {
    property position {
       position 13.0, 14.5, 0.2
       heading 90
       pitch 75
       bank 23
    }

    property render {
       model bug.mesh
    }
    
    property sound { 
       ambient_sound 'bugsound.wav' // override the default setting
    }
}
This is something I'd be heading to, from the content designers view (a rather bad example). It should be not that hard to implement this. This list would be separate - e.g. archetype definitions are per whole project, object definitions per level.
From the programmers view, the properties would have a defined set of fields, and should be able to self describe themselves. (renderPropDef.getFieldList(), etc.). Because the listeners to properties handle the actual view, the renderPropDef is an instance of the same class as for example soundPropDef, etc.
Image
User avatar
Falagard
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 2060
Joined: Thu Feb 26, 2004 12:11 am
Location: Toronto, Canada
x 3
Contact:

Post by Falagard »

steven wrote:@falagard Your object/component/behavior design seems to function like our object/component one.
But I fail to see the benefit of separating the behavior from the components.

Why not making specific components each with its own behavior?
Does it not simply add an additional indirection?
First let's be sure we're not hitting semantic problems here. I didn't read about your object/component design but it's entirely possible that your object is the same as my component and your component is the same as my behavior. If so, there's no difference - just the class names are different.

I don't have an object, then a component, then a behavior. I have components and behaviors.
Dom
Halfling
Posts: 57
Joined: Wed Jul 14, 2004 10:12 am
Location: Berlin

Post by Dom »

eugen, roger - i'll consider that.

volca, I agree that callbacks/listeners would do that. I like the possibility for the reverse look-ups as it helped me in the past to connect distinct systems without intense inter-webbing while allowing flexible scripting.

You say "only slaves to your code" ... I think this means that you have to wrap all the Ogre functionality? I.e. a component for position (wrapping an ogre entity), a component for rendering (wrapping mesh) ?

Falagard,
Indeed one need to pay attention what people understand under certain words - for example volca's 'properties' could be my 'components'
Another example is: manager/service/server/system
User avatar
volca
Gnome
Posts: 393
Joined: Thu Dec 08, 2005 9:57 pm
x 1
Contact:

Post by volca »

Dom wrote: volca, I agree that callbacks/listeners would do that. I like the possibility for the reverse look-ups as it helped me in the past to connect distinct systems without intense inter-webbing while allowing flexible scripting.

You say "only slaves to your code" ... I think this means that you have to wrap all the Ogre functionality? I.e. a component for position (wrapping an ogre entity), a component for rendering (wrapping mesh) ?
Well, the property(component) does not wrap any class itself. It is a source of data for the given service which needs it/realizes it. That means f.ex. RenderModel property (if such existed) having one field string - modelName:
The RenderService listens to all the messages from propertyGroup that holds the properties of this kind, and for any change, it adds/removes/changes the entity attached to the sceneNode.
The sceneNode is updated with messages from Position property.

Etc.

The PhysicsService, if it was written, would listen to the Physics properties and to position. It will use different classes to implement the physics, and will be the source of contact events and such.

There is one thing probably important to mention: There is only a little place to implement object behavior directly using the properties, that would be way too inflexible. So every object has script list, and these scripts listen to the events happening in the game and react to them (to be designed).

Please note that the target of my effort is not to build a new engine, but to mimic an existing one (DarkEngine).
Image
User avatar
anomalous_underdog
Kobold
Posts: 30
Joined: Tue Aug 21, 2007 8:20 pm

Post by anomalous_underdog »

here's a powerpoint presentation made by gas games about component based game objects in their game dungeon siege 1

http://www.drizzle.com/~scottb/gdc/game-objects.ppt
Dom
Halfling
Posts: 57
Joined: Wed Jul 14, 2004 10:12 am
Location: Berlin

Post by Dom »

volca, this is very interesting, thank you for the info.

Let me think a bit aloud: a Ogre-Service plugin could publish new property types to the system - i.e. position and geometry. This would be counterparts to Ogre's entity and mesh. If a property gets modified, a callback or message would add the property to the "modified/toUpdate" list of the manager. The Ogre manager also would 'publish' tasks i.e. for updating ogre objects. I am thinking of tasks as those (or a single one) may be easier distributed across multiple cores with less locks than one would maybe need if the callback modifies the object directly. A task would then "execute" the new property values onto the engine (that is wrapped by the service - in this case OGRE) counterparts.
I have no idea if it removes flexibility and makes things too complicated, but it sounds very interesting and something I might want to tryout. On the other hand it still sounds like a lot of properties and services that one has to create and maintain.

Btw. I have something similar to your properties. I have parameters and they are composed of basic (predefined) data-fields. Several parameters can be combined into a parameter-set, which is maybe a equivalent of your 'property' concept. This way new types can easily be created using data and still be modified by a GUI-Editor.
Fazel
Gnoblar
Posts: 2
Joined: Wed Oct 03, 2007 2:42 am

Post by Fazel »

Have any of you looked at the ideas presented at this site http://www.devmaster.net/articles/oo-game-design/

Game objects that would hold a list of actions and states. Actions would perform events which would trigger movements, changes of that object's states, sounds, etc. States would hold things like the objects health, or mana, or whatever else would be state worthy.

These could be then plugged into an object a runtime. An action could then query another object it happens to have interacted with, to see if it has the specific action or state that that action is suppose to change.

I haven't had time to implement this, but I was curious what other people think about this idea? The rest of the system may be a bit much at the moment but i think the action/state system is interesting.
User avatar
Zeal
Ogre Magi
Posts: 1260
Joined: Mon Aug 07, 2006 6:16 am
Location: Colorado Springs, CO USA

Post by Zeal »

Just read that article. I liked how he emphasized the separation between 'rendering' and 'logic', but I didnt quite understand the need for so many different 'game objects' (entity, action, state, and space)..

Kind of interesting, but it didnt really relate to this topic (he didnt talk about object composition hardly at all).
User avatar
volca
Gnome
Posts: 393
Joined: Thu Dec 08, 2005 9:57 pm
x 1
Contact:

Post by volca »

Dom wrote:volca, this is very interesting, thank you for the info.

Let me think a bit aloud: a Ogre-Service plugin could publish new property types to the system - i.e. position and geometry. This would be counterparts to Ogre's entity and mesh. If a property gets modified, a callback or message would add the property to the "modified/toUpdate" list of the manager. The Ogre manager also would 'publish' tasks i.e. for updating ogre objects. I am thinking of tasks as those (or a single one) may be easier distributed across multiple cores with less locks than one would maybe need if the callback modifies the object directly. A task would then "execute" the new property values onto the engine (that is wrapped by the service - in this case OGRE) counterparts.
I have no idea if it removes flexibility and makes things too complicated, but it sounds very interesting and something I might want to tryout. On the other hand it still sounds like a lot of properties and services that one has to create and maintain.

Btw. I have something similar to your properties. I have parameters and they are composed of basic (predefined) data-fields. Several parameters can be combined into a parameter-set, which is maybe a equivalent of your 'property' concept. This way new types can easily be created using data and still be modified by a GUI-Editor.
This is how I planned to do the asynchronous communication as well. The property definitions are stored in files, as the 3 games that should be handled (Thief 1, Thief 2 and System Shock 2) contain some differences in the definitions.

But actually, for now, I dropped the threading option, which can be seen as a wastage of a good and viable option, considering the separation. I spent some time thinking about that, and decided that if something can really be moved to a different thread, then it's the physics. I'll try to prepare the loop management code to be able to do this, as it should be possible to avoid the problems with threading as physics basically could prepare object position for the next frame, while the renderer is running the previous one. On the start of the next frame, the updated positions would be deployed synchronously.

It seems we are doing the things in a similar way. I see the self-description of the properties (or whatever they're called) as a very good thing. I use a kind of Variant implementation for the property fields, which even more improves the possibility to auto-generate the editor window for objects. No editor for now, but a replacement of DromED (ShockED) would surely be appreciated.
Image
User avatar
Zeal
Ogre Magi
Posts: 1260
Joined: Mon Aug 07, 2006 6:16 am
Location: Colorado Springs, CO USA

Post by Zeal »

So for a very basic example, could you do something like...

Start with a generic 'Component' base class. All your components (position, 3d model, all the 'things' that make up your game object...) will be sub classes of 'Component'. Then create a 'GameObject' class that has a list/vector of Component pointers. That way you could expand a GameObject to include pointers to any number of custom components (assuming the base Component class had all the interface functionality you needed, like a virtual 'update()' function, ect...).

Am I close? Or am I missing something..
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Post by KungFooMasta »

Yep, you have the basic principle down. :)

Some components will also have the need to communicate with other components (if they exist!) to carry out all their functionality. How they communicate or interact isn't a clear solution, IMO. Seems to be a mix of messages and direct calling, depending on your situation.

Also the idea of GameObjects having child GameObjects sounds pretty cool, but its only an idea at this point. (for me at least)
Creator of QuickGUI!
User avatar
Zeal
Ogre Magi
Posts: 1260
Joined: Mon Aug 07, 2006 6:16 am
Location: Colorado Springs, CO USA

Post by Zeal »

need to communicate with other components (if they exist!)
So to check to see if a GameObject has X component, you just number ALL your components (using a simple enum), and give the base Component class a 'getType()' method which would return this enum id? Then you could iterate through all Component* in your GameObject looking for a specific id (and when you find it, you know its position in the list). Right?
User avatar
JohnJ
OGRE Expert User
OGRE Expert User
Posts: 975
Joined: Thu Aug 04, 2005 4:14 am
Location: Santa Clara, California
x 4

Post by JohnJ »

Zeal wrote:So to check to see if a GameObject has X component, you just number ALL your components (using a simple enum), and give the base Component class a 'getType()' method which would return this enum id? Then you could iterate through all Component* in your GameObject looking for a specific id (and when you find it, you know its position in the list). Right?
That's one way to do it. If I use a component system, I'm planning to retreive other components by a string name (managing IDs and enums really defeats the purpose of a modular system, I think). For speed, each component can "prefetch" the pointers of the other modules, like I posted on page 3.

But I don't know how well this would work in a multithreaded or message based system.
User avatar
Wolfmanfx
OGRE Team Member
OGRE Team Member
Posts: 1525
Joined: Fri Feb 03, 2006 10:37 pm
Location: Austria - Leoben
x 99
Contact:

Post by Wolfmanfx »

offtopic: I have read the first page and this page so maybe i lost something :)
But what i understood is that all of you trying to implment something like a objective-c Falagards behaviour is similar to a prtotocol.
In objc you send message to an object and ask it things.
User avatar
Zeal
Ogre Magi
Posts: 1260
Joined: Mon Aug 07, 2006 6:16 am
Location: Colorado Springs, CO USA

Post by Zeal »

(managing IDs and enums really defeats the purpose of a modular system, I think).
Hmm I dont quite get that. Correct me if im wrong, but the 'modular/scripting' side does NOT give you the power to create new Components. The Components themselves have to be first hard coded in C, THEN you can 'compose' custom objects via scripting. And by compose I simply mean - select form a list of pre defined Components and 'group' them together (so a 'Tree' could have position, visual, and 'talkable' component if you wanted to make a 'tree that could talk' GameObject).

So I dont see why managing a enum for your hard coded Components would be that big of a deal?
User avatar
JohnJ
OGRE Expert User
OGRE Expert User
Posts: 975
Joined: Thu Aug 04, 2005 4:14 am
Location: Santa Clara, California
x 4

Post by JohnJ »

Zeal wrote:
(managing IDs and enums really defeats the purpose of a modular system, I think).
Hmm I dont quite get that. Correct me if im wrong, but the 'modular/scripting' side does NOT give you the power to create new Components. The Components themselves have to be first hard coded in C, THEN you can 'compose' custom objects via scripting. And by compose I simply mean - select form a list of pre defined Components and 'group' them together (so a 'Tree' could have position, visual, and 'talkable' component if you wanted to make a 'tree that could talk' GameObject).

So I dont see why managing a enum for your hard coded Components would be that big of a deal?
It probably won't be a big deal, provided you have a certain set of components and you're sure that's not going to change. I just think that this system is so well suited for a plugin-able component architecture that it would be almost a waste not to make each Component a truly self-contained module (compiler-wise), especially when it can be done with no loss in performance.
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Post by KungFooMasta »

I recently played around with factories (similar to plugins), and realized the only way to maintain a 'Type' property when allowing users to create their own Types on the fly was to use a string. It would be cool to allow appending to an enum, but that would probably be abused a lot.
Creator of QuickGUI!
Post Reply