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
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Component Based Objects?

Post by KungFooMasta »

I've read about this at various locations on the web, and it sounds like a really great idea. The problem? How to determine what good Components would be. I know this is somewhat game specific, but I'm curious if anybody has implemented this design in their own projects.

It is my understanding that you create a bunch of components, which can then be added to a Game Object. For example, I would make a class called "StaticObject", which inherited from GameObject, and added certain components that give it the functionality I desire.

So trying to determine what components I should have, at a basic level. I thought there should be a Renderable component, which consists of a SceneNode. And then maybe a Mesh component, which contains an Entity and name of mesh file, a Location component, which contains a position and orientation, and a Light component, which is basically an Ogre::Light.

Using Renderable, Mesh, Light, and Location components, I can create a "LightObject", for example a campfire. The question is, how do you go about initializing the components? The Mesh component needs to know what mesh file to use to create the entity. It also needs the Renderable component, so it can attach to the scene node and be drawn in the scene, and needs the Location component, to know how/where to position the scene node. The components seem pretty intertwined already, and I haven't really done anything complex.

Questions:
1. Are the components I had in mind too granular? What would be a better choice of components?

2. How would these Component Based Objects be initialized? (Say you wanted to create an object using "ninja.mesh", for example)
Creator of QuickGUI!
User avatar
Chris Jones
Lich
Posts: 1742
Joined: Tue Apr 05, 2005 1:11 pm
Location: Gosport, South England
x 1

Post by Chris Jones »

we have an Object/Component framework in OGE. The way you design your components might be different depending on the design of your engine, but in OGE we have different systems (e.g. Graphics, Physics etc).

so for a game object, you could attach a Graphics component, a Physics component etc. so a graphics component would contain a scene node and an entity for example.

we will also have common components, such as a position component. which graphics can use to read its position, physics would write to it. this is possibly rather specific to OGE though because of our design (each system is in a different thread)
User avatar
jomunoz
Goblin
Posts: 228
Joined: Wed Apr 13, 2005 5:07 pm
Location: Medellin - Colombia

Post by jomunoz »

This sounds to me like the decorator pattern. I think the Blender Game Engine use that type of approach, you can parent different objects, lights an other things called empties that are like scenenodes.
Also, to any object you can add a Sensor, Controller or Actuator that helps control different actions of the object.

You should check it out.
User avatar
volca
Gnome
Posts: 393
Joined: Thu Dec 08, 2005 9:57 pm
x 1
Contact:

Post by volca »

This seems to me very simmilar to the DarkEngine approach.

Game objects are consisted of properties (each property is kind a dynamic struct). The properties are inherited, if not implemented in the object, from the archetype object the object inherits from. Archetypes have object id < 0, and serve the purpose of pre-designed objects (abstract) - doors have the right model, physics settings, AI vision blocking, etc. Concrete objects (ID > 0) are created with only those properties they need to change (Position for example).

Some properties are inherited, some are not, some only for a specific situations.

There are some other goodies, like metaproperties - those are archetypes which mask the properties of the object itself, having higher priority. This means you can, based on some even for example, change an object using a metaproperty (M-Wooden), so a previously non-burnable object can be burnt using fire.

The types of stimulus (fire in this example) and they're receptrons (reaction on the stimulus) are resolved in Stim/Receptron system, which also uses properties.

I hope this is an interesting reaction.

Edit:
To your question about initialization: I think the usage of listener to the components would be ideal. If a component is added/changed/removed, the "MeshComponentManager" would take the appropriate action, adding/replacing/removing entity from the scene-node of the object.
Image
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 »

Thanks for the replies. I'm surprised to find so few implementing this idea, I've seen it mentioned in a few online articles, and GPU Gems 5 and 6. (I don't own the books, so I couldn't read them in depth, unfortunately)

http://cowboyprogramming.com/2007/01/05 ... -heirachy/

I guess the main issue is where to draw the line between who has the information, and who is using the information. A lot of components need to talk to each other to manage and/or perform specific functions. For example, there could be an "Animation" component, which interacts with the "Mesh" component, if it exists, and plays, stops, handles animations, etc. The problem is, even if the structure of a particular Game Object is created by its components, I have to somehow feed the data to the components. For example, I create a Game Object called "X". Class X contains a Mesh Component. Naturally a Mesh Component needs a mesh file in order to create an entity. So does the X constructor require a Mesh File name? Perhaps my original understanding of Component Based Objects is incorrect. Maybe you don't create a class called X. Instead, you simply use "GameObject" classes everywhere, and populate them with Components. This way you create the Component ( ie new CMesh("ninja.mesh",...) ) and then add it to the GameObject. This is probably the way to go.

But now say you have a GameObject, which may or may not have a Mesh Component, Render Component, etc. How can you find out, or more importantly, how can you get the GO's with Render Components to render into the scene?
Creator of QuickGUI!
cdkeito
Orc
Posts: 468
Joined: Sat Jan 27, 2007 12:06 pm
Contact:

Post by cdkeito »

in yake there is something like it : model !
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 found some code from somebody's comment on the article in the URL in my previous post, it clears things up. Basically you iterate through the GameObjects and see if it has a Render Component, and if so, Render it! :)

Its hard to imagine how this would work with an editor. Maybe you create a Game Object, and then a list of Components appear. Then the user selects what components to add, and hits "Add". :lol:
Creator of QuickGUI!
User avatar
Game_Ender
Ogre Magi
Posts: 1269
Joined: Wed May 25, 2005 2:31 am
Location: Rockville, MD, USA

Post by Game_Ender »

Is that done generically? Or does the update function need to be changed everytime you add a new component.
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 »

How I would implement it is to have a base "Component" class, that has an ID_Type, and takes a pointer to the owner GameObject. There is also a "virtual Component::update()" function called every time you update your game. The Type is not unique, but you can only have at most 1 type of Component. (for example, if you have a "Visual" component, and made from that a "VisualSphere" and "VisualCube". Bad examples, but they are partly from GPU Gems. I haven't gotten far enough to have good examples)

The GPU Gems 6 example has a family id and component id, and some template manager, etc. Instead, I would just have the Component class have a function called "clone()", and use that to create multiple instances of a component.

Also, the GameComponent has a map<ComponentType,Component*>, and updates them when you call GameObject->update(). (This would be my approach anyway)
Creator of QuickGUI!
mirlix
Goblin
Posts: 225
Joined: Mon May 01, 2006 12:03 am
Location: Germany
x 5

Post by mirlix »

Im writing a Component System at the moment for my game. i have a first early version of the system running, so if anyone is interested i can upload the code, even if its not near production code, some features are missing and some parts arent documented right now but it works.

I combined the Component System with a Message System, so maybe its not what are looking for, i also use functionpointer a lot of times. I use 3 basic classes for my system. A interface for componets and messages and a ComponentOwner class. Each Owner can have several Components to describe a gameobject. All communication between Components is through messages which helps to make the Components independent from each other. But even with them some Components need other to work properly. So a Component know which type of other Component he need to work. When this Component gets added to a Owner he checks if the Owner have all needed Components, if not he create the needed. This isnt implemented in my code yet.

If any component needs parameters for his creation they get passed through a map, often created with a xml file.
Example for a Model component would be the following mapentry
Model ninja.mesh
User avatar
volca
Gnome
Posts: 393
Joined: Thu Dec 08, 2005 9:57 pm
x 1
Contact:

Post by volca »

Do you plan the components to be holding the represented data or only the values?

I can imagine you can have two different attitudes:
1. Each component is only a value storage
then you don't have to design the components to be actually doing anything, they only expose a value list, some setters and getters, and are organized in some kind of container, so every time a change happens to a component in this container, through the interface of this container, a listener is notified about the change - Mesh Component listener would load the mesh, request the object's node from the Node listener (or somewhere else), and attach the entity.

This, in my opinion, leads to a cleaner design. You separate the model from the view.
The result is maybe not that compact, and easy to understand.
Also, note that this can lead to rapid prototyping of game objects, and easier editing, as you can do game object inheritance as I described in the prev. post.

2. Each component also manages the data it represents
This would mean you have numerous component types, and they actually do the work they're data represent. In this case, each component will also have to implement some kind of self-description, so you can base an editor on this.

This is a big unknown for me. I'd like to see how it looks/works. Maybe I miss some important point. For example - how the object's code will be done? Is there a class that represents the object itself?

Just curious which way you'll select. I'm implementing the option 1 in openDarkEngine - even though there the name is not "component" but "property".
Image
mirlix
Goblin
Posts: 225
Joined: Mon May 01, 2006 12:03 am
Location: Germany
x 5

Post by mirlix »

Im using option 2, my components have their data and do the actual work.
I like this more because the data and the code which uses the data is in one place.
There isnt a class which will represent a object, there is only the ComponentOwner which is a Object. But he can add/delete every Component during runtime, so he is a rather flexible object. The nice thing about this is, when you have the basic elements for a game as components, yout dont need a programmer anymore. The gamedesinger simply can describe ComponentOwner by saying a Player has a 3DModel componet, a sound component,a physiks component, a keyboard component, etc . Which also enables rapid prototying, With a editor he can change this during runtime, so in theory, a complete game can be created while the designer is playing it, if all needed Components are coded. In the real world this will only work to a certain degree, any game has some special components which only this games need and has to be created by the programmer but i hope you get the idea.
Some aspect i really like is that it is easy to write tests for the components .
Every component has a set of messages he uses. To test a component i can use this components and check if he reacts the right way, i dont need the rest of the game, which leads to a small and powerful testenviroment.

Do you use message too? I really like the combination of Compoents and messages, its quit powerfull i think.
.
User avatar
volca
Gnome
Posts: 393
Joined: Thu Dec 08, 2005 9:57 pm
x 1
Contact:

Post by volca »

Interesting, thanks for the info.
mirlix wrote: Do you use message too? I really like the combination of Compoents and messages, its quit powerfull i think.
.
Yes. To describe using the same words, I group the components not by owner, but by type. This group has a notification system, so every listener which needs to know the position of the object will listen to Position component group, and will receive messages about the change in the value for every change in that component type, for all objects. Same for other component types.

Also, I did not mention Links yet. Those are a different concept. The engine uses them to link objects together. Basic link type is an inheritance link, which inherits property (component) values from object to other object. There are numerous link types, for example ControlDevice link will route any incomming messages of a certain kind to the object(s) that the link targets, etc.

(Imagine a switch linked with a light with ControlDevice link, using the switch will cause a SwitchOn/SwitchOff message to appear, and this message will be routed to the light, which reacts to this signal)
Image
rogma
Halfling
Posts: 73
Joined: Fri May 07, 2004 5:03 pm
Location: Issy les Moulineaux, France
Contact:

Post by rogma »

I am using a component system combined whith model/view approach (with notify/init/close...) :
* a central hierarchical model (objects have children) and eaxh object has component (trait)
* several views on traits. These views are attached on traits automatically (using a static registration mecanism)

For example, I have a component named 'Solid' that contains the mesh name. On the display viewpoint, it is used to attach the mesh to the corresponding node. On the physical viewpoint, the same Solid is used for collision.

Basically I have now the following components :
* Positionned (store object position)
* Oriented (store objetc orientation)
* Mobile (sotre speed)
* Solid (store 'volume' information)
* Massive (store mass)
* Laser (to say that the objetc is a laser canon)
* ForceGenerator (for object that generates force)
* ...

It is split in very small parts, separating concerns almost orthogonally. It proved valuable for rapid prototyping. Adding a new trait is easy, and it conveys it own behaviour.



You can look
* the code here in subversion,
* API here
* some documentation (in french sory) here
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 »

I'm using behavior injection in my game engine.

The basic idea is that a component is just a container for behaviors.

Behaviors are self contained classes but may query for other behaviors within a component and act upon them.

Instead of having a GameObject base class, and then a MeshGameObject that creates an Entity and adds it to the scene, I have a MeshBehavior class which gets added to a Component.

It solves the problem of multiple inheritance and/or having to add functionality constantly to base classes within an inheritance tree.

For example, imagine you have an NPC character. In a different system you might have a GameObject base class, then a derived MeshGameObject class, and then a derived CharacterGameObject class, and finally NPCGameObject. Now imagine you want to add some functionality, such as the ability to take damage from bullets or fire. You would have to figure out where to add that functionality.

In my case you'd have a MeshBehavior which knows how to load a mesh and add it to the scene, a CharacterBehavior that knows how to move a character around and has health, an NPCBehavior that has scripted events support and an inventory and is aware of the CharacterBehavior and controls it, and a DamageBehavior that knows how to take fire and bullet damage and is aware of the CharacterBehavior and applies damage from bullets and fire.

Instances of each of those behaviors are added to a Component instance through a data driven method (a config file for a particular NPC) at runtime. New behaviors can be added easily. A library of behaviors can be put together and mixed and matched across different types of games.
mirlix
Goblin
Posts: 225
Joined: Mon May 01, 2006 12:03 am
Location: Germany
x 5

Post by mirlix »

For me it sounds like your behaviors is like a component and your component is a ComponentOwner in my system. Because my system does exactly what you describe , so they are maybe differents word for the same idea.

So how are your exp. with this system, does it work well. How easy is it to use etc.
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 »

@volca:

I would be using approach 2 also. Even if I had a listener to know when a Component was created, how would I know what data to populate it with? Basically when you create the Component you populate it, and then add it to the GameObject. I'm not sure what what a ComponentOwner is, and how it differs from my view of a GameObject.

@mirlix:

I would be interested to see how your message system works. :)

I thought of some other good component types: "CollisionShape", which can derive into "SphereShape", "CapsuleShape", "MeshShape", etc. And also "CollisionHandler", which can derive into "SoundCollision" (a noise produced when collision occurs, like walking into a plant, or bullet hitting an object).

Falagard, I think we we have similar ideas in mind. I wouldn't create multiple Game objects and have a heirarchy, I would just create GameObjects everywhere, and let the user configure them. For convenience I would probably make some default configured GO's. Like selecting a mesh from a listbox and clicking in the scene would create a GO with Render, Mesh, and Placement components right off the bat. Of course you'd be able to add/remove components at runtime. Whenever I get around to tinkering with this, it will be awesome. :D
Creator of QuickGUI!
User avatar
anomalous_underdog
Kobold
Posts: 30
Joined: Tue Aug 21, 2007 8:20 pm

Post by anomalous_underdog »

I also plan on using Component based systems

One of my ideas is having a destructible component, which practically gives the game object some hit points. You could give this to a crate to make it destructible, to the player (of course), to npc's that can be killed, et al.

This collaborates with the animatable component. Whenever the object gets hit, and it has an animatable and renderable component, it should play the "onHit" or "onDeath" animation or something like that.

I also plan on making a pathfinder component which gives the object movement. This also collaborates with the animatable component such that it should automatically play the "onMove" animation when it moves, which could be a walk animation for a person, wheels turning animation for a car, et al

I also have a SensorArea component which triggers events when the player steps on its collision mesh (something like in Starcraft's map editor). The same goes for probably some sort of SensorTimer component.

I plan the game objects to communicate to each other via a scripts.



That listener/message notification system is new to me. Sounds like an idea worth looking into.

about that light, so with a listener approach, maybe my light can listen on the switch's value whenever it changes, and turn itself off or on correspondingly.

or as a different approach, whenever the switch is activated, it runs a script that turns the light on or off.

kinda like the difference between polling and event-driven.
mirlix
Goblin
Posts: 225
Joined: Mon May 01, 2006 12:03 am
Location: Germany
x 5

Post by mirlix »

You can find my code here nemesis-interactive.com/objectsystem.zip (The code is under the LGPL)

Bear in mind this is working code, it isnt finished, some features are missing and not all features are documented right now. At the moment it is only some Proof of Concept work of mine, but i hope it give you a good insight in my idea. If you have any questions,ideas comments post them here or for realtime communication use ICQ number 236815808 or jabber id mirlix@jabber.ccc.de, sometime it is easier to explain code in direct chat.
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 »

Thanks for sharing. :)

I'm still new with Boost, hopefully that didn't affect my understanding of your code. What are the main advantages of using a message system? It looks like messages are tied to functions, so when a message is read, its corresponding function is executed. This could also be done by asking the GameObject owner for a particular Component, dynamic cast it and use it directly, right?
Creator of QuickGUI!
User avatar
xavier
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 9481
Joined: Fri Feb 18, 2005 2:03 am
Location: Dublin, CA, US
x 22

Post by xavier »

KungFooMasta wrote:This could also be done by asking the GameObject owner for a particular Component, dynamic cast it and use it directly, right?
Messaging is intended for asynchronous execution, where messages can be dealt with at the convenience of the receiving thread (process, application, whatever). Calling methods directly is obviously synchronous.

A well-designed messaging strategy is usually essential for decoupling of systems from one another. In your case, where you call methods directly, you may need to include headers for the actual receiving classes (altho in many cases you can just include headers for a callback interface class). But you still have baked in system interdependencies into the design this way -- what if you want to include another system on the receiving end? If you just post messages to a common bulletin board or message queue, any interested parties can join in without any need to alter the sending code.
Do you need help? What have you tried?

Image

Angels can fly because they take themselves lightly.
mirlix
Goblin
Posts: 225
Joined: Mon May 01, 2006 12:03 am
Location: Germany
x 5

Post by mirlix »

One main aspect why i uses messages is, that i can switch the one component with another and they dont need the have the same interface, only response to the same messages. This is really helpful when you want to change whole subsystems, they dont need the same interfaces only the same messages, its not the perfect solution but it helps.
Another reason i use messages is that every component belongs to a group and every group to a thread, when i send a message the systems checks if the sender and reciever are in the same thread, is this the case the message get send, if not the message gets in a queue of the thread. So i have a automated threadin build in the system. With some effort it is even possible to load balance the threads by mobing groups from one thread in another.
This concept can extended with network abilities, so message gets sends over the network.
A nice side effect is that debugging gets a lot easier, cause i can trace every message and log it, so i know everything what happens.
For this i have to trade off some speed, direct functioncalls are faster, but i think it is worth it.
REiNDEeR
Greenskin
Posts: 149
Joined: Sat Apr 14, 2007 1:27 pm

Post by REiNDEeR »

KungFooMasta wrote:Thanks for the replies. I'm surprised to find so few implementing this idea, I've seen it mentioned in a few online articles, and GPU Gems 5 and 6. (I don't own the books, so I couldn't read them in depth, unfortunately)

http://cowboyprogramming.com/2007/01/05 ... -heirachy/
It looks like he forgot or doesnt know about the concept of an interface by looking at the "TRADITIONAL DEEP HIERARCHIES" part in his article, the rest is based on that error.

The code provided by one of the people replying to it says it all (http://www.unseen-academy.de/componentSystem.html).

Read this short rant on design patterns: http://www.javaranch.com/patterns/
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 looks like he forgot or doesnt know about the concept of an interface by looking at the "TRADITIONAL DEEP HIERARCHIES" part in his article, the rest is based on that error.
Can you elaborate? The problem is not interface... that specifies the way a user can access and use a particular object. The problem is that the traditional heirarchy approach tries to save on coding by creating classes that share functionality. But later on you come across entity objects that have common traits with different entity objects, and then suddenly you have multiple inheritance everywhere, and your classes become bloated and hard to maintain.

I somewhat agree with that rant on design patterns. If they don't fit in, don't try to squeeze them in. (For example, I don't completely understand how the Factory design pattern works, so I don't rush out to learn it and throw it in all my projects) But when it comes down to it, design patterns do solve a common re-occuring problem, so if you don't have the problem this pattern solves, or if you can make a solution that better fits your situation, go for it.

If you see a problem with the Component Based System attack it directly. From my viewpoint, I can't see how this design would be bad. I speak from personal experience regarding the traditional deep heirarchy, its a big time pain in the ass. If you spend tons and tons of time thinking about how to organize the heirarchy you will do well up to a certain point, but in the end you will think up some new functionality which defies the structure. So this modular approach wins easily. (what's not to like about this design?)
Creator of QuickGUI!
Lacero
Halfling
Posts: 72
Joined: Tue Feb 13, 2007 1:57 am

Post by Lacero »

KungFooMasta wrote:
It looks like he forgot or doesnt know about the concept of an interface by looking at the "TRADITIONAL DEEP HIERARCHIES" part in his article, the rest is based on that error.
Can you elaborate? The problem is not interface... that specifies the way a user can access and use a particular object. The problem is that the traditional heirarchy approach tries to save on coding by creating classes that share functionality. But later on you come across entity objects that have common traits with different entity objects, and then suddenly you have multiple inheritance everywhere, and your classes become bloated and hard to maintain.
Yeah, having a Grenade interface is fine, except 90% of the code for each type of grenade will be the same and you'll end up reimplementing it everywhere if you just use an interface. Using a has-a relationship seems much better to me, but I'm not far enough on in my own project to have got to the problem yet.

This is still an interesting thread htough, thanks for all the examples everyone.
Post Reply