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
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 »

The same messaging implementation Falagard detailed im using also for the last 3-4 years into the engine we develop here and it served us well (also is simple enough to be adjusted for multithreading porposes if u need). (there are also situations in which u wont want to use messaging at all and just call directly methods as i found out on the way)
My main problem was to decide wether to use fixed queues for specific threads or variate the queues for the thread being able to process it at the time. The idea is that there are too many types of messages and only a few threads (in general processors number - 1) able to run the available queues. And if u would want to have an optimal system then u need to run as many messages as quickly as possible without intersecting execution of the same type of message at any time.

I wonder how did u aproached this issue Falagard?
(i wouldnt hijack this thread with this question, would i?!)

another issue with this type of messaging system was that all the data sent into each message should be static (meaning i cannot be 100 percent certain a pointer sent within a message would be accessible when the message is executed, for example, considering sending an entity pointer into one message as a parameter, when executing the message there is no certainty that pointer is stil valid since alot can happen between sending the message and executing it - this was part of the reason we dont use messaging all the way all the time)
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 think we've covered the basics of a Component Based System. We've moved into Component Based communication, so I don't think you're off topic. I also thought about problems of sending pointers. How does a multi threaded situation work? Are Various GO's scattered across different threads? And can messages be sent from an object in one thread to an object in another? Sorry for the noob questions, I'm interested, but I also admit I know nothing about multi threaded design/development. :oops:
Creator of QuickGUI!
User avatar
steven
Gnoll
Posts: 657
Joined: Mon Feb 28, 2005 1:53 pm
Location: Australia - Canberra (ex - Switzerland - Geneva)
Contact:

Post by steven »

@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?

@eugen You reached exactly the same problems as I with the messages (ptr validity, use of static data, nb of messages type, ...) and reached the same conclusion that you need to use direct calls for some situations.

I believe now that direct calls are best used for simple, fast and very frequent updates such as position changes and such. Whereas messages are best for infrequent tasks that can be done asynchronously such as building a new object, assigning a new AI task, etc.

@KungFooMasta Multithreading a game engine is a subject in itself. And there are several threads about it. There is a bit of a religion war on the different approaches possible. IMO at the moment it is not clear which one is the "best" one (if there is one).
At your place I would try to review them and choose the one that suites you and - more important - that you are sure to understand and able to debug. Because debugging a MT application is not trivial :roll:
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 »

@steven
Yes, we use messages in general for selfcontained messages in which u dont need alot of info from outside. This aproach put to an end part of the messaging system being tottaly multithreaded since direct access deos mean more syncronization mechanisms and so on.

Im stil thinkering with the multithreading part as there is no easy solution if u want to make the system flexible enough. I kinda reached a conclusion in which separate threads should work on an atomic kind of tasks (we call them tasks the ones on the core system side, events/messages the one on the application logic side) which can execute separately from the system (like sound streaming in which there is not too much interaction with the data, networking, part of the physics system, specific logic algorithms like pathfinding, decision making implementations and so on)
While the data is in separate modules (a graphics module, a sound module and so on) they are all accessed within a single thread (aside from the special cases) though the api
@KungFooMasta
I would keep all GameObjects within one thread (possible one dll) and implement the logic there. They each instead gather components from different modules but that doesnt matter as long as they all update into the same thread.
There are no restrictions for messages regarding threads or even dlls.
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 »

Interesting. The more I learn about component-based architectures, the more useful and productive it sounds. I'm thinking about implementing something like this in my game engine, but there are a few questions I have:

1. How are per-frame updates handled? Is an update() function simply called for each component of each object each frame?

2. How does one component access another effeciently? I would imagine constantly calling owner->getComponent("Physics"), for example, could eat up a lot of performance when being called many times per frame per component per object.
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 »

@JohnJ - im also looking for a good way of implementing game logic into the engine so i have no definite answers
I wouldnt go that far on calling update every frame for every GO
i would define queues of execution based on how often do we want a component to update (generally there is alot of variation on that part so is better to handle this in way u wont call methods when u dont realy need to)
Calling efficiently means at least dont use strings to get the components. But i see not so often cases where components access another (as i see it, compoenents are more or less selfcontained objects that knows what to do independently of another). As for intercomponent calling i would pass components parameters at GO initialization as much as possible pointers so they have all the data they need. Then i would use events and messaging to transmit impulses to other GOs or components which are not part of the self GO
I would also define specific properties for components, one being Immortal which will tell for a specific period id (which at large can be the application lifetime, at small could be the GO lifetime) if a component will be destructed and when is safe to use the pointer thrustly. Also for this to work there should be a feedback mechanism that will alow components to know where to regain the pointers
As i see it, there are alot of improvements to be done but what im getting from the component based aproach is that there is alot of flexibility to get a good system
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 »

As for intercomponent calling i would pass components parameters at GO initialization as much as possible pointers so they have all the data they need.
That gives me an idea: (semi-pseudo-code)

Code: Select all

class GameObject
{
public:
	void addComponent(Component *c)
	{
		componentList->add(c);
		for component = each in componentList {
			component->notifyOwner(this);
			component->componentPrefetch();
		}
	}

	void removeComponent(Component *c)
	{ ... }

	Component *getComponent(String name)
	{ ... }

	void update()
	{ ... }

private:
	List componentList;
}

class Component
{
public:
	String getType() = 0;
	void notifyOwner(GameObject *obj) { owner = obj; }
	void componentPrefetch() = 0;
	void update() = 0;

private:
	GameObject *owner;
}



class CLocation: public Component
{
public:
	String getType() { return "CLocation"; }
	
	void componentPrefetch()
	{
		physics = owner->getComponent("CPhysics");
	}

	void setPosition(Vector3 pos)
	{
		this->pos = pos;
		if (physics)
			physics->setPosition(pos);
	}

	Vector3 getPosition()
	{
		return pos;
	}

	void update()
	{
		if (physics)
			pos = physics->getPosition();
	}

private:
	CPhysics *physics;
	Vector3 pos;
}
componentPrefetch() is called every time the object's component list changes, so the object can pre-call getComponent() and store the result in a local variable (for fast access).

This way you can access components by string name (which is a whole lot easier than accessing by number or maintaining an enumeration), and have optimal performance.
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 »

Yes, is a nice quick view implementation...
When i said the components shouldnt be gained by string i thought of looking for a component in more detalil than physics. For example, my solution would define each GO being a component on its own meaning all GOs u construct (offline or in editor) can be a part of other GOs. I would imagine storing all components (and therefore GOs) in a data type that would alow me quick access (like a vector) by an index or so
...like i said i dont have a clear implementation picture but choosing the component at initialization should be clearely defined by already implemented code in a common way for all GOs/components hardcoded or created at runtime
REiNDEeR
Greenskin
Posts: 149
Joined: Sat Apr 14, 2007 1:27 pm

Post by REiNDEeR »

KungFooMasta wrote:The key difference is when you use inheritance you fix the design at compile time. With the aggregation approach you make the Component things you add at runtime."
But does that mean you'll never have to write code again? I have a hard time imagining how a component editor would work for every object your gonna make without ever having to write extra code.
User avatar
steven
Gnoll
Posts: 657
Joined: Mon Feb 28, 2005 1:53 pm
Location: Australia - Canberra (ex - Switzerland - Geneva)
Contact:

Post by steven »

eugen wrote: I would imagine storing all components (and therefore GOs) in a data type that would alow me quick access (like a vector) by an index or so
Good idea - seems so obvious now I wonder why I haven't done it like this.

You idea of an Immortal tag is nice - but I prefer to have in each object a list of all the components. If a component will be destroyed it is "simply" removed from the list before the destruction of the component. So you don't need to test if the ptr to a component is still valid.
Or did I miss a usage case?
REiNDEeR wrote:But does that mean you'll never have to write code again? I have a hard time imagining how a component editor would work for every object your gonna make without ever having to write extra code.
I don't believe you will be able to make generic component that fits all game type. Very probably you will create overloaded components that are specialised and/or optimised for your game. Of course, with time your components will mature.
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 »

But does that mean you'll never have to write code again? I have a hard time imagining how a component editor would work for every object your gonna make without ever having to write extra code.
Well, obviously you still have to write code, but it seems that the component design can be so modular that creating new types of game objects actually becomes easier as you progress, as you build a set of reusable Component's.

At a certain point, you may be able to create new game objects entirely from existing components, which is where a component editor would be handy :)

But these are just my first impressions of the technique - I haven't actually implemented it in a completed game yet.
User avatar
syedhs
Silver Sponsor
Silver Sponsor
Posts: 2703
Joined: Mon Aug 29, 2005 3:24 pm
Location: Kuala Lumpur, Malaysia
x 51

Post by syedhs »

In general, I would say OO based class is nice, but if not designed correctly will incur more time (developing it) unnecessarily instead of actually helping. Over engineer tend to rear its ugly head easily here, so just be careful :wink:
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 »

I've been thinking about this technique some more, and I'm not quite sure how it would benefit complex functional objects.

For example, a rock that can be turned into a lightstone works just fine, but what about something more practical like a tank, for example. How would you implement a tank with a rotating turret and gun, complete with moving tracks?

I know how to do this the "traditional" way, but with components, you'd either have to make one big CTank component that implements the physics, audio, etc. all by itself (not an improvement), or scatter the tank operations into various components like CPhysics, CTankRenderable, CTurretRenderable, etc. (also not an improvement).
User avatar
Game_Ender
Ogre Magi
Posts: 1269
Joined: Wed May 25, 2005 2:31 am
Location: Rockville, MD, USA

Post by Game_Ender »

You are thinking about it wrong, you don't make a tank object or component. You build a tank out of your existing components and multiple GameObjects. You could have separate GameObjects for the turret, and body. These both would have Physics components, and the turret would have a weapons component. You could extra components for the animated treads etc.

The whole idea is not to specialize everything with "CMyVehicleType". If you just replace that with "MyVehicleTypeComponent" you haven't gotten anywhere.
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 all depends on your implementation. Are the rotating turret and gun separate meshes? You could implement tracks and the gun as animations.

I think at that point you might be breaking your object down uneccessarily.

Tank:
CRender
CMesh
CLocation
CAnimationManager
CMovement
CMeshShape

I haven't thought far enough to come up with how GameObjects handle creating and/or attaching other GameObjects, but this is what I would do for firing of projectiles.

Missile:
CRender
CMesh
CLocation
CVelocity
CCapsuleShape

I know I'm being very general about this, but until I actually attack this I can't really get into specifics. When I do I'll let whoever is interested know. (But don't hold your breath, I don't plan to start development until after QGUI Editor is released, and I haven't even started. :wink: )
Creator of QuickGUI!
mirlix
Goblin
Posts: 225
Joined: Mon May 01, 2006 12:03 am
Location: Germany
x 5

Post by mirlix »

When Im returning from Japan in two weeks i will make my Component System LGPL, so everyone who is interested can follow it, even when it isnt far yet

@KungFooMasta Please notify me when you starting your System so when can exchange ideas etc to improve our systems and helps with problems.
Maybe there is a way we can work together.

Anyone who wants to work on the system is highly welcome.
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 »

You could have separate GameObjects for the turret, and body. These both would have Physics components, and the turret would have a weapons component.
The turret and body would be implemented as bones, so I don't think you could really assign each to their own GameObject.
You could implement tracks and the gun as animations.
Possible, but what if the tracks are physically simulated to correctly roll over the terrain's contour? And with the turret, how would you include it in the rigid body physical simulation when it's a part of an animation?

Maybe I'm thinking about this all wrong, but it just seems that for anything but the most simple objects, a component system adds more complexity than it's worth.
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 »

Possible, but what if the tracks are physically simulated to correctly roll over the terrain's contour?
And you know how to do this in code? :P

As for the turret, I would make it a separate game object owned by the tank, and have the tank use it. You might have to make some specialized components specifically for tanks to control and make use of the turret.

For your idea with tracks, I'd really like to see this implemented in any way. Each invidual piece of track would have to be its own collision component, loosely connected to another. It also depends on the tightness of the tracks. Let me know how you plan to implement this. :wink:

I don't agree that a component system would only be suitable for simple objects. If you were only using simple objects, why use this design in the first place?

I have to run now..
Creator of QuickGUI!
User avatar
radioman
Greenskin
Posts: 132
Joined: Sun Dec 31, 2006 3:59 pm
Location: lithuania

Post by radioman »

..i like components, and use them, the system(my) is based in a way, that each one can access and use another & absolutly in dynamic way. All you need is interface header, and dll with that interface implementation. You add it to component list, and the same moment you have it, no compilation, no time wasting :lol:

..because every part of the system is component you can have 1001 component and in 523th access 687->546->566->25->54->.. wahtever ;}

example:

Code: Select all

MyCarComponent * car;
if(!this->GetEngine("superCar", to(car)))
{
  logerComponent->add("mising Car");
}
GetEngine/GetGame is automatic in component, so you don't have to think how soemthing works, or how to get something, just get access to it & use ;} Check component list & choice what you need ;}

..all component managment control center component, so you don't need to deal about init/release component if you don't want...

..i just begin expand this, but it seems work quite nice for me & i use it in one my game(i swear i make it whatever, someday.. ;])

..you can check there: http://code.google.com/p/miracle-intermedia/wiki/SDKs

..i now testing this idea practiculy on linux, because started on win ;}
peace & serenity
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 »

I don't agree that a component system would only be suitable for simple objects. If you were only using simple objects, why use this design in the first place?
Exactly :D. I'm hoping someone will reply who's done something near this level of complexity with a component design, because I'd really like to use a component system, but not unless it makes my work easier :)
Let me know how you plan to implement this. ;)
Well honestly, in my experience I've only implemented rolling tracks in a completed game, but I have a pretty good idea how I'll do dynamic tracks.

It actually depends how the tank will be implemented in PhysX. First I'd get the tank acting the way I want without regard to how the tracks will look. For example, each tank may be implemented as a car with 8 (or whatever) wheels with suspension on each side.

After I have the tanks acting like I want, I'll add the track animation. If, for example, the 16-wheeled car method is used, I can use the height of each wheel/spring to manipulate the track height at the given point. If another technique is used, I can perform a few raytraces on each side of the tank to determine the track heights.

But probably the "proper" way to do it would be to define each segment of the lower portion of the track individually in the physics engine, and let it do the rest. Obviously this will look a little better, but I think the "cheaper" method mentioned above would look just about as good.
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 »

Well here is the main thing. When developing any piece of code, it is a good practice to implement it piece by piece, no? And in putting in effort to making code modular, you can re-use it for other scenarios, right?

When it comes down to it, you will have to implement a tank in some form or another. This design just emphasizes making the *pieces* of code modular, so that you can re-use them if applicable. And even if your components seem to only work for the tank, you have the added benefit of being able to debug piece by piece. It's easier to analyze the inputs/outputs/behavior of the component, how it interacts with others, etc.

Simply put, Make the tank, but have the mentality of breaking up the fundamental functionality into Components. Component Based Objects is not a solution to how to build a tank. Its more of a way of thinking. Thats how I view it anyway.
Creator of QuickGUI!
mirlix
Goblin
Posts: 225
Joined: Mon May 01, 2006 12:03 am
Location: Germany
x 5

Post by mirlix »

I agree with KungFooMasta. Component Based Systems are simply an other why to think about your gameworld. Not one Object one class, but one task one component. This helps, like sayed before, to keep your code modular and reuseable.
User avatar
radioman
Greenskin
Posts: 132
Joined: Sun Dec 31, 2006 3:59 pm
Location: lithuania

Post by radioman »

one task one component
..and with that comes a litle overhead about coding time, but i think this way of coding brings more satisfaction, because you know what and where is it and how it works, and no matter how much component you have.

I can't say the same about many classes with mystical interhitance each other or something, because you lose control after a while... And think about compilation about 5000 classes each build ;] With component you have only ONE build.

Thats the point i choice components.
peace & serenity
User avatar
oddrose
Orc
Posts: 470
Joined: Thu Feb 15, 2007 2:08 pm
Location: Gothenburg, Sweden
Contact:

Post by oddrose »

For starters, I'm very excited about this design...the component based system. But as many have discussed...is the reusability worth the extra while? I mean, say you create your game engine for a specific project. What are the chances that you will use your engine more than a couple of times? (This is an honest question, I have no idea...) And if you end up using it 3-4 times I can't imagine it would be that much of a time saver?
User avatar
steven
Gnoll
Posts: 657
Joined: Mon Feb 28, 2005 1:53 pm
Location: Australia - Canberra (ex - Switzerland - Geneva)
Contact:

Post by steven »

I believe there is a misconception here.

The purpose of component-based object is not to code less but the flexibility it gives you
(and code reusability if you developed your components well - but IMO this is a bonus).

With it you can add/remove very easily a functionality from an object even in real time and/or data driven and/or with an editor.

For example, with a regular OO hierarchy try to envision how many objects you must expose to an editor .. and you must hard code it.
Whereas with component based object you can expose automatically ANY type of objects you create (based on components of course).

Another example of advantage: if you at the end of your project one of your designer who wants a "Talking and Walking Tree" you could well be in the situation where you must modify your whole "Plant" hierarchy.
With components you simply add a "Talk" and "Movable" components and you are done.
Post Reply