PDA

View Full Version : Game object/entity systems


tentons
12-15-2004, 06:53 PM
I've built a component-based system (in C++) where I can put game objects together from various components at runtime. It's pretty flexible (for a first attempt), but I know there's a mild overhead for this flexibility. I want to be able to compose objects like this, but I'm not sure if such an approach is even desirable unless you plan to do lots of on the fly object building (say, by allowing players to create custom spaceships or whatever from within the gameplay).

Then there's an event system which allows components to communicate indirectly. This is definitely a performance hit, but it is very flexible and works well. (I prefer this to callbacks or some other "dangerous" method where pointers can cause trouble when objects are deleted and then get events after the fact.)

I don't mind the performance hits, and I do want to create the best system possible which can be used across many games. This seems to be a good way to go, so far, because I can just code up some new components and have game objects with completely new behaviors--for a price in performance, though.

I've really fallen in love with C# and want to move to it for my 4th project, which will probably start in early 2006. I'm learning about it now, hoping to find ways to implement similar things in better ways with that language.

How do you guys approach the issue of object/entity management in your games?

James C. Smith
12-15-2004, 08:53 PM
Component, components, component. We usually call them “plug-ins”. I hate deep class hierarchies. I usually try to avoid extending a concrete class by deriving a new class from it. Instead, I prefer to add new behavior by making new types of plug-in components that can be added at run time. It is common to have plug-in plugged into other plug-ins. I have standard editors for building component hierarchies at run time and standard file formats for storing them on disk.

I also love to use message passing. You can send a message to an entity telling it that it just took 7 hit points of damage. The message is broadcast to each plug-in attached to the entities and each of those plug-in passes it along to their plug-ins.

Any time a game designer/level designer asks me to code up a specific game rule or power-up type I never do exactly what they want but instead make some plug-in that they can use to build what they want and many other things. If they wanted a touch activated teleporter pad I would make a plug-in that triggers an “action” (a special class of plug-in) when the entity the plug-in is attached to is touched by another entity. I would then make an action that relocated entities and other actions that plays sound effects and visual effects. The level designer could then assemble an entity that uses a standard rendering plug-in to make the entity look like a teleported pad and then add the TriggerActionWhenTounched plug-in to the entity. He could then go into the TriggerActionWhenTounched plug-in and plug-into it the RelocateEntity, a PlaySound action, and a SpawnVisualEffect action. This internal implementation of TriggerActionWhenTounched would probably just be a message handler that responds to the CollisionDetected messages sent to an entity (and it’s plug-ins) any time one entity collides with (touches) another entity. The RelocateEntity action would probably send a YouWereJustRelacateded message to the entity that was moves so plug-ins on it could react to being relocated (teleported)

Nemesis
12-16-2004, 12:52 AM
That took several reads to absorb, but I begin to see the advantages (I think). So just to clarify: rather that extend your entity class for every combination of behaviours required, you maintain a class hierarchy (or interface implementation) for several types of pluggable behaviours that can be attached dynamically to an entity. I guess that should indeed cut down on the width and depth of the class hierarchy.. it's a neat idea!

It's a shame there doesn't seem to be plenty of literature on these kind of game architecture issues.. or maybe I haven't found the right books yet.

tentons
12-16-2004, 05:02 AM
I have standard editors for building component hierarchies at run time...
I'd love to see a screenshot of that.

...and standard file formats for storing them on disk.
Currently, I build my objects from XML definitions on demand. I don't store binary "plug-ins" on disk, but I might move to that later. I'd like to achieve what The Sims achieved, and be able to offer downloadable objects that can be dropped into a directory and then accessible from the game at any point.

I also love to use message passing.
Ok, I seem to be going along the same development path as you. That's good, since it's enough corroborating proof that it works well.

If they wanted a touch activated teleporter pad I would make a plug-in that triggers an “action” (a special class of plug-in) when the entity the plug-in is attached to is touched by another entity.
So the "action" would itself be another plug-in/component which receives a message triggered from the plug-in/component that got touched?

It's a shame there doesn't seem to be plenty of literature on these kind of game architecture issues.. or maybe I haven't found the right books yet.
I don't think it's widely discussed, because I haven't found much on it, either. One reason I'm asking is because I am not sure if I'm on the right track or if there's something better that everyone else already knows about that I don't. :)

Nutter2000
12-16-2004, 06:18 AM
I think the system described is often called Embodied Agent AI where you seperate the "physical" or body game object from it's AI which is encapsulated in a "metaphysical" or brain class.

There's a good essay on it over at Alex Champandard's site AI Depot (http://ai-depot.com/GameAI/Embodied.html)

As far as I can tell your system takes it even further and seperates the AI further using message handlers. Seems like a good idea, is there much overhead to doing that?

tentons
12-16-2004, 06:51 AM
I think the system described is often called Embodied Agent AI....
I actually put several design patterns together to achieve my current system, which probably isn't as flexible as James' but sounds quite similar. The component pattern, chain of command pattern, etc. I guess, being patterns of design, there's bound to be other names for the same type of system.

Kai Backman
12-16-2004, 09:15 AM
Someone must have read my mind, I'm just working with the component system to make a more flexible save game design for our upcoming project. :)

Thank you for your excellent comments Jason and James, I definitely got some great ideas from you (I need to look into nesting components next..).

Here is a good link to some slides about saving such component systems:
http://www.drizzle.com/~scottb/gdc/game-objects_files/frame.htm

Nutter2000
12-16-2004, 09:33 AM
I actually put several design patterns together to achieve my current system, which probably isn't as flexible as James' but sounds quite similar. The component pattern, chain of command pattern, etc. I guess, being patterns of design, there's bound to be other names for the same type of system.Yes true, I really only ment it as an example of what to search for, but yes the underlying design patterns are called by many different names, including unprintable ones when it's 2am and somethings not working ;)

I was debating wether to go the extra and incorporate something like that in my latest system or wether to just hack something for now.
I think from reading this thread I'll probably go for something similar to what James and yourself mentioned.

@Nemesis
I find Design Patterns (http://www.amazon.co.uk/exec/obidos/ASIN/0201633612/qid=1103218310/ref=sr_8_xs_ap_i1_xgl/026-6397899-0231630) a good book for, well, design patterns.

milo
12-16-2004, 10:56 AM
Component, components, component. We usually call them “plug-ins”.
You're probably already used to the name "plug-ins", but this sounds more like the standard GoF Strategy Pattern (http://c2.com/cgi/wiki?StrategyPattern).

--milo
http://www.starshatter.com

tentons
12-16-2004, 01:22 PM
The Publisher/Subscriber pattern (http://www.openloop.com/softwareEngineering/patterns/designPattern/dPattern_publisherSubscriber.htm) is pretty similar to how I implemented my event system. After I learned Java some time back, I decided this was a great way to handle things. In a project before that, I had a system using explicit callbacks. The publisher/subscriber method works very well, and without explicit callbacks (a good thing IMHO). You do have to keep track of who's subscribing and who's publishing, but it's worth the extra effort.

I'm currently working out the 2.0 version, which will utilize a single "dispatcher" to manage all the events in the system. I find this necessary because the current system allows objects to send events directly to one another, but that created problems when I started deleting objects as the game was being played. So I had to work around that. But with a dispatcher, if an object sends an event to an object that's deleted, no harm is done since it will stop at the dispatcher and not go to some invalid address instead.

I found lots of subtle issues like this cropping up, so I've learned a lot from it.

I also haven't noticed a speed hit (unscientifically judging with FPS), but I have a small number of objects in my current game (less than 50 at any time so far). Still, it is worth the flexibility you gain IMHO.

Nemesis
12-16-2004, 03:58 PM
@Nemesis
I find Design Patterns (http://www.amazon.co.uk/exec/obidos/ASIN/0201633612/qid=1103218310/ref=sr_8_xs_ap_i1_xgl/026-6397899-0231630) a good book for, well, design patterns.
Ah the famous GOF book.. I need to grab me one! :) I'm only aware of a few design patterns that I usually look up with google.

gmcbay
12-16-2004, 05:10 PM
On the subject of event systems, I've recently fallen deeply in love with signals and slots. There are a few really good implementations, including one in boost and one called "sigslot". I'm using sigslot myself, because I find the boost implementation to be somewhat ugly to look at and I'm a bit of a code snob.

Between a decent sigslot library and boost's wonderful smart pointer wrappers, C++ is almost a bareable language to use.

Rod Hyde
12-17-2004, 03:35 AM
Ah the famous GOF book.. I need to grab me one! :) I'm only aware of a few design patterns that I usually look up with google.
This is a link to a page containing a very good Powerpoint tutorial on Pattern Oriented Software Architecture (http://www.cs.wustl.edu/~schmidt/patterns/patterns.html). It is geared towards patterns for concurrent and networked objects.

--- Edit
I've been looking through the associated books (POSA-1 and POSA-2). Very good (and the penny dropped more than once or twice - "ah, so that's what it is called"). How long before someone writes "Patterns for Game Programming?"

--- Rod

tentons
12-17-2004, 11:29 AM
Between a decent sigslot library and boost's wonderful smart pointer wrappers, C++ is almost a bareable language to use.
Less than almost, to me.

I really can't stand header files or the lack of support for explicit interface classes (pure abstract works, but it's more of a pain). But I really can't stand header files. :) C# is so much nicer. *boohoo*

The thing is, though, once you get solutions for these issues hammered out, it's less of a pain. My next engine will be a lot easier to create simply because I've solved a lot of the problems already, and it's more of an iterative refinement. So that allows me to swallow the fact that my next 2 games will be in C++.

tentons
12-17-2004, 11:37 AM
Firgured I'd get back on topic and ask how you handle entity management?

I have a "master" object which manages and updates all the active entities. It deletes those who are marked for destruction, and adds any who've been created recently (ie, last update). So basically all the entities register themselves with this master controller, and the controller is updated by the game loop (or not, in the case of a pause). This ties in pretty heavily with every other sub-system, from events to physics, so adding and deleting objects requires care.

Next time, I'm thinking of using "handles" for objects instead of passing pointers around. Anyone have experience with such a system applied to game entities?

Uhfgood
12-17-2004, 11:43 AM
You guys make my head hurt.

GBGames
12-17-2004, 12:20 PM
How long before someone writes "Patterns for Game Programming?"[/I]


http://www.gamasutra.com/patterns/

B-)

gmcbay
12-17-2004, 12:25 PM
I use boost smart pointers (shared_ptr) to solve those problems where different objects in different subsystems might need references to the same object. It does reference counting internally and will automatically delete the underlying object when the reference count drops to zero. Quick & dirty garbage collection.

I honestly think anyone who is still managing their own raw pointers must hate themselves. Smart pointers are such an amazingly useful thing in C++ and the overhead they bring is negligible, even on the PalmOS port of my engine.

Triple_Fox
12-18-2004, 12:02 AM
This is using Python: I give each entity its own class. But at initialization each instance is passed a dictionary of attributes and a reference to an object that contains all the relevant gameplay data(the map, other objects), which it can do whatever it wants with. If an object needs to be messaged that can be added as needed, since Python makes it very simple to do so.

My policy is generally to let each entity have a maximum of power to control things, and then whittle it down when I actually code it. It's worked well in the tests I've done so far.

Siebharinn
12-20-2004, 09:54 PM
Sorry for reviving a sleeping thread, but this is very interesting. I've been steeped in the deep-hiearchy, long inheritance chain style of OOP.

However, after reading this (http://www.asbahr.com/paper2html/paper2.htm), I've been looking at a similar pattern: attaching function objects as attributes to a class to control behavior, rather than subclassing repeatedly. I like the approach, but it feels somewhat foreign to me right now.

The question that I have, specifically for James but others are welcome to chime in, can you describe the functional interface that your plug-ins use? There has to be a minimum level of knowledge on both sides of the plug-in. I can't get my head around adding a plug-in to detect collisions; you still have to know what information to pass to the plug-in to enable it to understand the collision. I can see plug-ins for modifying existing behavior, but how do you use it to add a fundamental behavior, like collision detection?