Following is an excerpt from GDAlgorithms-list (http://lists.sourceforge.net/lists/listinfo/gdalgorithms-list) ================================================================================ From: "Mark Wayland" (Mwayland^torus.com.au) Subject: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 10:07:06 +1100 Hey all, In an effort to remove as much dynamic memory allocation from our in-game game loop, I was wondering how many of you approached the problem of having entities which inherit behaviours/attributes from other entities? At the moment we have factories associated with entities. Certain classes of frequently used entities are "pooled" and allocated quickly, but others simply default to the standard allocator - resulting in a fragmented heap. I have written a memory allocator that makes it trivial to allocate sub-heaps and very inexpensive to effectively wipe the heap "clean", and is about 50 times faster than the default ones - but fragmentation is still an issue. Any better ideas? How do you handle multiple different entity types and allocation of them? Cheers, Mark ================================================================================ From: "Eric Yiskis" (erk^sammystudios.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Tue, 28 Jan 2003 18:13:00 -0800 Hi Mark, It seems like the worst fragmentation problems occur when you have small objects mixed in a heap with large objects. A pool has no fragmentation because all the objects are the same size. So what we have is a "spectrum of fragmentation". 8-) It seems like a good solution is to have heaps for different sizes of objects. In practice, maybe you would only have two heaps: "big stuff" (geometry, textures, layouts, etc.) and "small stuff" (nodes in linked lists, instanced classes, etc.) This seems like compromise solution on the spectrum that is closer to the "pool" side without the hard "one size only" restriction of the pool. - Eric ================================================================================ From: "Johnson, James" (James.Johnson^sierra.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed poo l allocation Date: Tue, 28 Jan 2003 18:33:41 -0800 Check out boost.org, specifically their memory pool implementation http://www.boost.org/libs/pool/doc/index.html. It has a options for ordered free's limiting fragmentation and fast frees. It's implemented via C++ templates, is easy to use, free to use (no GPL or LGPL), well documented, and much faster than standard new/delete/malloc/free. Even if you don't use it, its a fantastic reference. Did I mention it's cross platform? It is. With regard to behaviors, this may or may not help but... Behaviors have always been tricky. Behaviors can be classified as intrinsic and extrinsic. I try to make intrinsic behaviors small, limited in scope and dependency, and generally unaffected by moderate design changes. For example, vector addition will not change unless you change to a non Cartesian coordinate system - a fundamental change. Extrinsic behaviors tend to be the opposite. They are usually complex, sometimes require coordination or information outside the object/entity, and generally change frequently (usually at the designer's whim). Finding a the right balance between intrinsic and extrinsic behaviors is challenging. The system I'm working on separates entity data and behavior. Entity structure is defined by a schema. Behaviors are encapsulated as a series of commands that require certain schema entries and sometimes require certain data values (e.g. type must be XYZ). This has several potential benefits and limitations: * behaviors can be applied to all entities that meet the behavior schema requirements * creating or deriving new behaviors is simple * changes in entity schema may break behaviors * behaviors may interpret the entity schema inconsistently * naive entity implementations can lead to slow data access James ================================================================================ From: "Mark Wayland" (Mwayland^torus.com.au) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 16:51:52 +1100 James, Thanks for your comments. The memory manager I wrote does treat small and large allocations differently, so that's not really the problem. The problem we face is that the C++ inheritance mechanism is used to derive new entity types. The only "clean" way (that I'm aware) of creating these new entity types is to either create a factory which may pool them, or simply dynamically allocate them... or are your entities all the same form of datastructure (allowing easy pooling) with some other form of extensibility? For instance, we may have a collision-only entity in the form of a end-of-level trigger or we may have a graphical object, an AI guy or whatever. We currently have "behaviour" type attributes such as logic, graphics, physics which determines which methods on the entity get called in which order. Issues such as entity priorities arise and so forth ... How do you manage all these different forms of entities without large inheritance chains, creating code cache problems for some consoles? Is there a better way? Cheers, Mark ================================================================================ From: "Awen Limbourg" (alimbourg^eden)-studios.fr> Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 09:55:32 +0100 Considering your problem, i can't figure how frequently you are removing/adding (delete/new) entities from your memory: does that happen everytime everywhere in your 'level', or only at init/shutdown time ? We do have polymorphic entities, but that's not a problem since the 'scenaric memory' is allocated once per level init (we have per level stats), and flushed globally at the end of it. Each entity is queued one after the other, relentlessly. For the illimited monster generation situation, we have fixed size pools, and each time one is killed, its slot is 'freed' and a new one is ready to go, and again no dynamic stuff. We have dynamic ressources (streaming), but the scenaric stuff is not a part of that, for many many reasons... Is that your problem ? So, could you expose a little bit further ? ================================================================================ From: Noel Llopis (llopis^comcast.net) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Tue, 28 Jan 2003 20:25:25 -0500 On Wed, 29 Jan 2003 10:07:06 +1100 Mark Wayland (Mwayland^torus.com.au) wrote: > In an effort to remove as much dynamic memory allocation from our > in-game game loop, I was wondering how many of you approached the > problem of having entities which inherit behaviours/attributes from > other entities? In MechAssault we unfortunately [1] have quite a deep game-object hierarchy, with classes inheriting behaviors from their parents. Dynamic allocation of new entities and other objects happens very frequently during gameplay. We solved the problem by using memory pools in two different ways: - Specific objects that were created often and had the same size were given a memory pool of their own, with fixed-size slots. An example of this was messages, physics handlers, or pathfinding nodes. - Other objects that were created often but had all sorts of different sizes were put in a common pool system, with several pools that could hold objects up to a certain size, and each object was allocated in the smallest pool it would fit. Game entities fell in this category. The pooling happened by overriding operator new and delete on the classes that had a pool assigned to them, so there was no need to change any other part of the code. Each of the pools allocates memory blocks that are multiples of 4KB (the specific size is determined by their slot size and expected use), and they are never released once they are allocated. Before we were using pools, we were having spikes of up to one thousand allocations per frame (no, I'm not kidding). Once we added the pools there would be one allocation every once in a long while, usually when you punched a whole in a building or took a building down. > At the moment we have factories associated with entities. Certain > classes of frequently used entities are "pooled" and allocated quickly, > but others simply default to the standard allocator - resulting in a > fragmented heap. For whatever is worth, on the Xbox, thanks to their virtual memory system, I found it totally impossible to fragment the memory in any way that would affect the program. I even ran a few tests to stress test their memory system, and I never ran into a situation where an allocation would fail even though there was enough free memory. I understand it is a much bigger deal in other consoles though. --Noel (llopis^comcast.net) [1] Unfortunately not because of the dynamic memory allocations, which were not a problem in the end, but mostly because of the ugly and inflexible design they create. Modeling object behavior with C++ inheritance is asking for trouble. In the future I'm hoping to use a new system that relies heavily on composition and *data inheritance* instead. ================================================================================ From: "Thatcher Ulrich" (tu^tulrich.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 10:11:07 -0500 On Jan 28, 2003 at 08:25 -0500, Noel Llopis wrote: > > > At the moment we have factories associated with entities. Certain > > classes of frequently used entities are "pooled" and allocated > > quickly, but others simply default to the standard allocator - > > resulting in a fragmented heap. > > For whatever is worth, on the Xbox, thanks to their virtual memory > system What virtual memory system??? Are you saying the Xbox compacts memory somehow, or pages to disk? I'm pretty sure it doesn't (I could be wrong though). > I found it totally impossible to fragment the memory in any way > that would affect the program. I even ran a few tests to stress test > their memory system, and I never ran into a situation where an > allocation would fail even though there was enough free memory. I suspect it just has a decent malloc in the c runtime, like Win2K and *unlike* some older versions of Windows. Again I could be wrong, so correct me... -- Thatcher Ulrich http://tulrich.com ================================================================================ From: Noel Llopis (llopis^comcast.net) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 10:32:49 -0500 On Wed, 29 Jan 2003 10:11:07 -0500 Thatcher Ulrich (tu^tulrich.com) wrote: > > For whatever is worth, on the Xbox, thanks to their virtual memory > > system > > What virtual memory system??? Are you saying the Xbox compacts memory > somehow, or pages to disk? I'm pretty sure it doesn't (I could be > wrong though). I should have really called it "virtual addressing". No, it doesn't save anything to disk like a full virtual memory implementation, but it gives you a much larger virtual address space than the 64 MB of physical memory it has. That way you can frag the hell out of the physical memory, but it can always piece together a set of virtually-contiguous 4 KB blocks. --Noel ================================================================================ From: "Jamie Fowlston" (jamief^qubesoft.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 16:50:57 -0000 surely this leaves you with horrendous performance, though? j ================================================================================ From: "Ivan-Assen Ivanov" (assen^haemimont.bg) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 18:59:45 +0200 > surely this leaves you with horrendous performance, though? Why would it? Remapping of addresses is something done "for free" by x86 processors; it's the swapping out to actual disk part that makes virtual memory "slow". ================================================================================ From: Noel Llopis (llopis^comcast.net) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 12:07:47 -0500 On Wed, 29 Jan 2003 16:50:57 +0000 Jamie Fowlston (jamief^qubesoft.com) wrote: [... about the Xbox's virtual addressing...] > surely this leaves you with horrendous performance, though? Amazingly enough, it's not bad at all... most of the time. Without getting into details (consoles are funny things, I'm not really sure how much I'm really allowed to say without getting too specific) dynamic allocations were very fast, until you trash the system so much that all of the sudden a single allocation takes 300-500 ms all by itself! I imagine the virtual addressing system was compacting pages or something along those lines. That's actually what pushed us to use pools for the objects that are created dynamically during the game. But as I said, the pools are hooked up by overloading operator new and delete for the class, so you can still created them like you did before without affecting any existing code. MechAssault made heavy usage of dynamic allocation because of the really dynamic world, and how you can destroy just about everything, and cause all sorts of wild effects. For a game that doesn't use dynamic allocations to that extreme, the virtual addressing system might be perfectly fine. We only saw those spikes in performance when things got wild and we were trying to do several hundred allocations per frame. --Noel ================================================================================ From: Tom Forsyth (tomf^muckyfoot.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed poo l allocation Date: Wed, 29 Jan 2003 17:09:29 -0000 Not really - it's the same system as on a PC, just without the abilitiy to swap to disk. Cache lines are filled at less than 4k granularity anyway. The biggest extra cost is the increase in TLB misses, which hurts slightly, but not by a huge amount. Tom Forsyth - Muckyfoot bloke and Microsoft MVP. This email is the product of your deranged imagination, and does not in any way imply existence of the author. ================================================================================ From: "Jamie Fowlston" (jamief^qubesoft.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 17:47:47 -0000 it's not the remapping of the addresses that worries me, it's the random access of physical memory... it may be a groundless fear, however :) j ================================================================================ From: "Mat Noguchi" (matthewn^microsoft.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 09:57:08 -0800 It is. :) MSN ================================================================================ From: Tom Forsyth (tomf^muckyfoot.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed poo l allocation Date: Wed, 29 Jan 2003 18:08:09 -0000 Random access of physical memory is fine as long as you do it at large enough granularity. 4k is fine. OK, that's a slight simplification, there's some secondary effects, but they're (a) smallish (b) highly dependent on memory architecture (c) largely hidden by the look-ahead cache on decent CPUs and (d) lost in the general noise of execution. Wouldn't worry about it except in very specific cases where you are running very tight code that all fits in the cache, does long repeats of data, very predictable fetch patterns, and you know the target hardware. So maybe if you're writing a software VS pipe or something like that you'll notice the difference. But in general code - nah, it's lost in the noise. Tom Forsyth - Muckyfoot bloke and Microsoft MVP. This email is the product of your deranged imagination, and does not in any way imply existence of the author. ================================================================================ From: "Jamie Fowlston" (jamief^qubesoft.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 18:26:15 -0000 well, depends on the latency of your memory, and the granularity of your data in physical memory, surely? if you have high latency in your ram chips (rambus, anyone?) and you've chopped your data into tiny pieces (e.g. 1 byte... i'm sure something so silly isn't possible with the remapping of addresses, but i hope you follow my point :) and scattered it across the physical address space, i'd expect performance to suffer. of course, it may well be that the latency isn't that bad and you can't really chop it into small enough pieces to really suffer anyway.... j ================================================================================ From: "Chris Butcher (BUNGIE)" (cbutcher^microsoft.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 10:31:30 -0800 (This is too console/hardware-specific for the list, but it's short...) If you're writing a software vertex pipe on Xbox then you will certainly be using physical rather than virtually mapped memory, and probably write-combining cache behavior as well. So it's not a problem. One huge advantage of the virtual memory mapping is that it accelerates heap-driven access patterns massively. Without spending any time thinking about your memory access, you can get a significant fraction of the peak performance. It also lets you have some really braindead memory access and allocation patterns without getting pathologically bad performance (STL, anyone?) You can certainly make the argument that this lets programmers try to do stuff that they really shouldn't be thinking about attempting on a console. ObAlgorithms: I absolutely agree with Noel that using C++ inheritance to provide game object behavior is a terrible idea. I've ranted about this before, but the prime reasons I see for using your own inheritance scheme would be: total control over message handling, multiple inheritance, total control over allocation and garbage collection, better script / C separation. -- Chris Butcher Rendering & Simulation Lead Halo 2 | Bungie Studios (butcher^bungie.com) ================================================================================ From: Noel Llopis (llopis^comcast.net) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 13:40:15 -0500 On Wed, 29 Jan 2003 18:26:15 +0000 Jamie Fowlston (jamief^qubesoft.com) wrote: > of course, it may well be that the latency isn't that bad and you can't > really chop it into small enough pieces to really suffer anyway.... In the PC/Xbox architecture I believe that the smallest chunk of memory that the virtual addressing system deals with is 4 KB, so you are not going to be hurting your cache performance (an L1 cache line is 32 bytes). Even in the extreme case of a request that tries to read the last byte in a 4 KB block and the first byte in the next 4KB block, even if they were contiguous in physical memory it would result in two separate requests from memory. --Noel ================================================================================ From: "Eric Yiskis" (erk^sammystudios.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 10:42:32 -0800 Hi Mark, As far as the "avoiding inheritance" part, (which would allow you to have more modular pieces you could pool) you could use a component system. Component systems have huge advantages not only for memory allocation, but for being able to mix and match components in ways you couldn't do with a hierarchy. You get the same code reusability as inheritance, but the system is much more flexible. Of course, it has more overhead too, but I think it's well worth the trade off's. Scott Bilas (Gas Powered Games) gave an excellent talk on component systems at the last GDC. I also gave a talk about such a system at a local IGDA meeting. If you are interested, Scott's presentation is available and/or I could send you mine. Basically, inheritance is evil because you end up implementing a feature in one branch of the inheritance tree that later you want to use in another branch of the tree. What ends up happening is that the code gets a cut/paste job, or bubbles up in the class hierarchy. Alternatively, the functions can be separated out (along with their associated data) and then accessed by both spots... At which point you have made it into a component! By switching from an "is a" to a "has a" relationship, an object can "have" any piece of functionality attached to it. -Eric ================================================================================ From: "Johnson, James" (James.Johnson^sierra.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed poo l allocation Date: Wed, 29 Jan 2003 10:52:36 -0800 All our entities are the same data structure. Behaviors are completely externalized from entity data, and so their derivation hierarchy does not impact entity structure at all. Conceptually the system looks more like C than C++ in this respect. However the behaviors are defined as classes and use derivation for specialization. At the end of the day you'll have a set of static behaviors which operate on dynamic allocated entities (or data sets). James ================================================================================ From: Noel Llopis (llopis^comcast.net) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 14:16:07 -0500 > ObAlgorithms: I absolutely agree with Noel that using C++ inheritance to > provide game object behavior is a terrible idea. I've ranted about this > before, but the prime reasons I see for using your own inheritance > scheme would be: total control over message handling, multiple > inheritance, total control over allocation and garbage collection, > better script / C separation. When I said I disliked using C++ inheritance for modeling behavior I meant any sort of code-inheritance. Rolling your own version of inheritance doesn't seem to help any with respect to modeling something that does not want to fit the "tree shape" of inheritance. I'm much more a proponent of a composition-based system. Entities can own several behaviors or attributes. It is data-driven and can dynamically change during program execution. I *do* like data-inheritance, so designers can create new entities by inheriting the attributes of another entity and overriding the parts they want to change. But that doesn't involve any code-based inheritance, it's just more of a management tool for them. Scott Bilas described a system very much like that in a GDC talk last year (slides can be found here http://www.drizzle.com/~scottb/gdc/). Basically, the most concrete C++ class I'd like to see in a game is something along the lines of an Actor class. I don't want to see a Monster class, and certainly not Troll, Giant, and Goblin classes!! --Noel ================================================================================ From: Brian Hook (hook_l^pyrogon.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 11:20:29 -0800 >you have made it into a component! By switching from an "is a" to a >"has a" relationship, an object can "have" any piece of >functionality attached to it. Also known as an "aggregation" system. The problem that no language today has solved (that I'm aware of) is that what we normally use aggregation and/or inheritance for can and does change radically depending on your needs. You might use inheritance for overriding or augmenting behaviour. When you override, you typically don't call back up to your parent's implementation, but this is rife with obvious problems if the parent needs to do some super secret private stuff. With augmenting, you still call into the parent but only after/before you've done other setup stuff. This is also prone to problems. There is no clean solution to this (if there is, I'd love to hear about it), simply because different users or classes have different needs. Sometimes a base class MUST have final say on some member function, but sometimes a child class must also have final say on some member function -- who wins? Sadly, the advantages of having a single monolithic class with lots of flags and crap like that are still significant. With the elegance of polymorphism come all kinds of real-life headaches. Brian ================================================================================ From: "Johnson, James" (James.Johnson^sierra.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed poo l allocation Date: Wed, 29 Jan 2003 11:40:48 -0800 Mark, in this type of system, generally, what is the overhead you speak of? I assume the answer is gaining access to a specific component of an entity. Implementation wise this means your entity aggregates components, and therefore accessing a specific component could be as simple as a table lookup. This doesn't sound too costly, so I eagerly await your answer. Could you give us a run down of the benefits and limitation. Alternatively send a link to your presentation. Thanks, James ================================================================================ From: "Eric Yiskis" (erk^sammystudios.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 12:08:03 -0800 I agree with what you are saying about augmenting existing classes. I think the big gotcha with class hierarchies with respect to creating actors is that it tightly couples unrelated functions. For example, I might have a "Guard" character that inherits: Guard->AIChar->SkinnedAnimatable->Renderable->Task; and a "Door" mechanic that inherits: Door->Renderable->Task. If I want to add "AI" to my door, I'm in trouble! The problem is that through inheritance, I've coupled "AI" to "Rendering" which doesn't make sense. The component system makes things better in this area. AI can be a component, and "rendering" can be a hierarchy of components: SkinnedAnimatable->Renderable, and by decoupling the functionality adding AI to the door is no problem. Also, augmenting classes in the "render hierarchy" makes sense because they have the same functional goal. Of course, that hierarchy has the same problems you mention, but at least the hierarchy is smaller and related. 8-) -Eric ================================================================================ From: "Yordan Gyurchev" (yordan^gyurchev.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 20:08:22 -0000 > All our entities are the same data structure. Behaviors are completely > externalized from entity data, and so their derivation hierarchy does not > impact entity structure at all. Conceptually the system looks more like C > than C++ in this respect. However the behaviors are defined as classes and > use derivation for specialization. Isn't that the "flyweight design pattern"? If I'm not wrong when you make a change to your data structure you end up recompiling most of your source code. When you change something in your data structure (and things change even if the design was perfect - and with most games it is not) there is the constant problem of "it not working" and sometimes "not working" is more obscure than just not compiling. how do you deal with these problems? > Alternatively, the functions can be separated out (along with their > associated data) and then accessed by both spots... At which point > you have made it into a component! By switching from an "is a" to a > "has a" relationship, an object can "have" any piece of functionality > attached to it. That seems to be the trend in general with C++ (not only game code). People (or at least people that write articles in CUJ) have been saying that for two years now. Yet, I'm still tempted by inhertiance. Where can I find your presentation? -Yordan ================================================================================ From: "Charles Nicholson" (cnicholson^sammystudios.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 12:45:43 -0800 >> Alternatively, the functions can be separated out (along with their=20 >> associated data) and then accessed by both spots... At which point you=20 >> have made it into a component! By switching from an "is a" to a "has=20 >> a" relationship, an object can "have" any piece of functionality=20 >> attached to it. >That seems to be the trend in general with C++ (not only game code). People (or at least people that write articles in CUJ) have been >saying that for two years now. Yet, I'm still tempted by inhertiance. Where can I find your presentation? People are starting to realize that inheritance, though it seems natural, often isn't a great way to define certain aspects of an object. My personal opinion is that this is a Wittgenstein-style language issue- we're confusing what it means to "be" an object, and the result of that confusion is poor engineering. To C++ at the code level, an "object" is an instance of a class, no more, no less. To your game at a much higher level, an "object" is a higher-level entity that doesn't necessarily ONLY exist as code. It exists as a composition of code, artwork, AI scripts, event scripts, designer-tuned parameters, etc... The reason I think using inheritance gives people headaches and nastily-engineered solutions is because the C++ class model is too low-level in this context to say "This object IS-A door, and it also IS-A AI". Everything relaxes nicely and flexibly when your low-level base Entity/Object/Actor class can HAVE-A set of attributes that define its high-level type/behavior. I've always thought that inheritance is best used when defining attributes on the same conceptual 'level' or 'context' as the class itself. For example, your C++ Object class may represent a skinned AI'd Door that you can drive a tank with, but as far as IS-A, well... Is it reference counted? =20 Does it come from a Pool? =20 Do any template policy classes control its behavior? Those are the kinds of questions that are contextually "correct" to ask about an object's IS-A-ness. It feels correct to me to be able to ask those questions about a C++ class. Conversely, it feels wrong to me to ask questions like "Is it a door?" right next to "How should it release its resources?" I guess what I'm saying is that it feels na=EFve to model high-level attributes using low-level class inheritance. Intuitively, as a software engineering problem, it just seems like it's the wrong place to do it. Defer assigning a high-level "type" to your objects until as late as possible, then they are more generic. My $0.02. Regards, Charles Nicholson ================================================================================ From: Chris Hecker (checker^d6.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 13:51:46 -0800 >People are starting to realize that inheritance, though it seems >natural, often isn't a great way to define certain aspects of an object. As was said earlier, this statement is certainly true for "code inheritance". In data, it gets a little unclear, since it depends on how you define "inheritance" (for example, is mixin inheritance, etc.?). However, everybody agrees (or should) that doing your game's type and object system in the programming language is doomed for non-toy systems. It has to be data based. There is finally getting to be a good critical mass of information out there about this. Scott Bilas's work is online, as was stated earlier. Chris Butcher described the Halo 1 system a bit on this list during the last incarnation of this thread...I assume that's archived somewhere. Hopefully Eric Yiskis will put his IGDA slides online somewhere (I'm 100% sure Jason @ IGDA.org would be happy to host them, Eric). The Looking Glass object system used in Thief finally got written up by Doug Church for a nice talk in Korea last year, and I've got his slides on my site: Object Systems - Doug Church http://www.d6.com/users/checker/ObjSys.ppt Doug's talk briefly covers the Dungeon Siege system and the Halo system as well in comparison (from what's available publicly and from email conversations). And, Alex Duran is doing a talk at GDC on the latest work at ION Storm for Deus Ex 2 and Thief 3, and I believe he's also talking to other developers, so hopefully it will be an overall state-of-the-art talk in March. It should be a great talk. If you've got an object system like the ones above but different in important ways and you've shipped a game with it, or are close enough to shipping to have a list of real pros and cons, mail me and I'll put you in touch with Alex. Chris ================================================================================ From: "Mark Wayland" (Mwayland^torus.com.au) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 09:47:18 +1100 Awen, Thanks for your comments... > So, could you expose a little bit further ? (for those a bit sqeemish, close your eyes ;-) ) We have scenarios like when you kill a guard, he effectively turns into a pickup of sorts. This pickup has physics and collision, but also other properties that affect the player's interaction with the game world - such as it may encumber the player, it may make other guards more aggressive etc. As these entities only exist when the player does something, and the other entities cease to exist, it seems like a waste of memory to keep both around at the same time? As I mentioned to another fellow, I had an idea where I could have a double-ended pool of two different entity types - in this case, a guard and a pickup, as the more guards there are, the less pickups and vica versa. Allocate guards from one end and the pickups from the other end? We already use pools extensively, but I thought perhaps there may be some better mechanism than manually specifying pool sizes and specially handling the cases where the pool runs out etc (I guess we always have to do this). We presently handle this via the entity factory class. The entity factory may (or may not) use pools to allocate from. It is basically setup on a per entity class basis, which is kinda painful to maintain (ie. we run out of RAM, so we have to remove N types of entity A and add M types of entity B). I was curious to see if anyone had much better ideas that they'd like to share. Thanks again for your thoughts. Cheers, Mark ================================================================================ From: "Johnson, James" (James.Johnson^sierra.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed poo l allocation Date: Wed, 29 Jan 2003 14:54:04 -0800 You are quite right. The flyweight pattern can introduce compilation dependencies resulting in the recompilation of the entire project. But this result is an implementation choice that ultimately depends on how many levels of indirection you can live with. Our entity utilizes a dynamic property set which is configured at creation time. It's intrinsic functionality are get/set property, add/remove association, and add/remove aggregation. We utilize a variant type and hash table for data storage. This is why extrinsic behaviors (for us) are fast and accessing entity data (for us) is somewhat slow. Classifying our system under the flyweight pattern is somewhat confusing given the point of view I've describe our system. With regard to the flyweight pattern our behaviors are the shared resource (intrinsic data), the entities are extrinsic. Other than the interpretation of entity properties in a consistent manor we've had no other problems. As for performance there is always the option of compiling entity schemas directly into classes eliminating the hash table. James ================================================================================ From: "Kyle Wilson" (kyle^gamearchitect.net) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 18:06:58 -0500 > Object Systems - Doug Church > http://www.d6.com/users/checker/ObjSys.ppt Cool, thanks for the link! > And, Alex Duran is doing a talk at GDC on the latest work at ION > Storm for > Deus Ex 2 and Thief 3, and I believe he's also talking to other > developers, > so hopefully it will be an overall state-of-the-art talk in March. [PLUG] Also, I'm going to be moderating a roundtable on game object structure this year, which I proposed in the hope that we could discuss some of the same issues we've been talking about in this thread. I think our industry has reached a tipping point in terms of object count and complexity that makes the prevailing game object style of the last few years -- complex objects with deep hierarchies that deal with multiple areas of responsibility -- unfeasible. I'm really interested in hearing how other teams are handling this shift before Noel and I start redesigning our game object system later this year. I know what Scott Bilas and Rob Fermier are doing, but are other teams making the same move toward component-based objects? And if so, how do they handle the issues that arise involving communications between and dependencies between components? Anyway, come to the roundtable. It'll be great. :) [/PLUG] Kyle ================================================================================ From: Mark Danks (mdanks^STORMFRONT.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed po ol allocation Date: Wed, 29 Jan 2003 15:45:46 -0800 We are currently taking a different approach than "complex objects with deep hierarchies" as mentioned below. The number of one-off objects, or ones which have some subset of abilities, but not all, etc. has gotten out of control for us. On LotR: The Two Towers, we kept pushing abilities of the classes farther up the tree, until we had really large base classes. The current approach we are doing is with something called "attributes." Attributes can be things like collision, tick, AI, script event handling, etc. There is a base class which is a container for the attributes and you just add attributes as needed for the object. Even our script-side objects can add new attributes via script, so if you want to suddenly have something like "I can catch on fire", you add the "catch on fire attribute" to the object, and now all of the other objects in the game can deal with that attribute. The main difference that I see between this and a pure data driven design is that the attributes can have run-time code associated with them. A trivial example is our tick attribute and debugTick attribute. In release mode, the debugTick attribute doesn't get called, so we don't waste any performance calling stuff which doesn't matter...or blow the I/D caches on the PS2 :-) The nice thing about attributes is that they don't depend on each other. The collision attribute doesn't care about the script attribute nor the AI attribute. When we added AI to some of our pickups, only the pickups which cared about it got the attribute. This had made our traditional object class hierarchy fairly small and shallow. We have a bunch of different attributes, but they are orthogonal to the actual class hierarchy and can be mixed and matched (ie, reused) among the actual different game objects (like characters or pickups). Instead of creating monolithic object classes, we just combine from a bunch of little pieces. Later, Mark ============================== = (mdanks^stormfront.com) = Technical Director PS2/XBox = http://www.danks.org/mark ============================== ================================================================================ From: "Eric Yiskis" (erk^sammystudios.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 16:07:54 -0800 (Woops, I forgot we posted it...) My component presentation is at: http://www.igda.org/sandiego/flash_site.html Click on "Meeting Notes" Then click on "November 2002: Advanced Data Driven Design" There is a link to the presentation at the bottom of the summary window... -Eric ================================================================================ From: "Eric Yiskis" (erk^sammystudios.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 16:13:17 -0800 Ack! I mean't "Chapter Reports" instead of "meeting notes"... Sorry for spamming the list... http://www.igda.org/sandiego/flash_site.html Click on "Chapter Reports" Then click on "November 2002: Advanced Data Driven Design" There is a link to the presentation at the bottom of the summary window... -Eric ================================================================================ From: "Kyle Wilson" (kyle^gamearchitect.net) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 19:24:26 -0500 Mark Danks wrote: > The current approach we are doing is with something called "attributes." > Attributes can be things like collision, tick, AI, script event handling, > etc. Okay, I'm intrigued... so attributes are classes, derived from some base attribute class? That sounds a lot like a lite version of Scott Bilas' component-based object system for Dungeon Siege. But how do you get a particular attribute from an object? Do they have string identifiers? And how do you resolve the type of an attribute you've gotten? Is the caller expected to know the type of the attribute it's asking for and cast it appropriately? Kyle ================================================================================ From: Charles Bloom (cbloom^cbloom.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 17:29:12 -0800 There are pretty extensive threads on this stuff in the archives of this list. ---------------------------------------------------- Charles Bloom (cbloom^cbloom.com) www.cbloom.com ================================================================================ From: "Jon Watte" (hplus^mindcontrol.org) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 18:04:23 -0800 > for two years now. Yet, I'm still tempted by inhertiance. Where can I find > your presentation? I think it's perfectly valid to inherit interfaces (i e, pure or mostly pure abstract base classes). I've worked on several large systems that used inheritance of functionality or for extension, and it always breaks down at some point. What I'm of two minds about is dynamic vs static interface discovery. COM and C++ let you QueryInterface()/dynamic_cast<> to any other interface you want, which may expose interfaces that you don't particularly want exposed through the interface that the initial query is coming in from. You can fix this by providing explicit interface query functions for each interface you'd like to expose from each other interface, but in some cases (like, oh, say, something like "IActor" :-) that ends up being the kitchen sink, and it prevents you from dynamically adding to the system at runtime. Cheers, / h+ ================================================================================ From: "Thatcher Ulrich" (tu^tulrich.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 22:11:22 -0500 On Jan 29, 2003 at 01:51 -0800, Chris Hecker wrote: > > However, everybody agrees (or should) that doing your game's type > and object system in the programming language is doomed for non-toy > systems. It has to be data based. I don't agree with that, at all. "Doomed" is way too harsh -- maybe I would agree with: doing your game's type and object system in the programming language will bring you misery. Which isn't saying much -- I have yet to see any shipping game's object system, up close and personal, that *wasn't* a prescription for some sort of misery, but I'll check out those links. -- Thatcher Ulrich http://tulrich.com ================================================================================ From: Chris Hecker (checker^d6.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Wed, 29 Jan 2003 22:05:21 -0800 At 22:11 1/29/2003 -0500, Thatcher Ulrich wrote: >On Jan 29, 2003 at 01:51 -0800, Chris Hecker wrote: > > However, everybody agrees (or should) that doing your game's type > > and object system in the programming language is doomed for non-toy > > systems. It has to be data based. >I don't agree with that, at all. "Doomed" is way too harsh I tend to use the term "doomed" more often than most people. For example, I think the industry is doomed, too. :) However I consider myself an optimist in general! Go figure. Maybe I define "doomed" differently. ObAlgorithms: Every time I've seen a code-based hierarchy, the base class was 18 miles long and you had to recompile the world to change anything. Whether that leads to misery or doom depends on the size of your team, I suppose. Chris ================================================================================ From: "Matt Newport" (matt.newport^nicelycrafted.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 11:53:03 -0000 Interesting presentation. I have a question about the way your template/instance system works: do you have a single level of inheritance (e.g. a locked door inheriting from / overriding a base door) or is their support for more levels (e.g. a metal locked door or a wooden locked door)? On a previous project I worked on there was a system for describing actors whereby inheritance chains could be built up and whilst it had some advantages it also caused problems when changes at the top of the chain would propagate all the way down, to the frustration of the designers. I think I would tend to favour a single level despite the occasional benefits offered by multiple levels. Matt. ================================================================================ From: "Jamie Fowlston" (jamief^qubesoft.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 12:04:16 -0000 seems to me that when you specify a virtual method, you often also want to specify it as a prefix or postfix to the equivalent method in the derived class... would be nice to have the option.... j ================================================================================ From: Noel Llopis (llopis^comcast.net) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 07:27:34 -0500 On Wed, 29 Jan 2003 16:13:17 -0800 Eric Yiskis (erk^sammystudios.com) wrote: > Ack! I mean't "Chapter Reports" instead of "meeting notes"... Sorry for > spamming the list... > > http://www.igda.org/sandiego/flash_site.html > > Click on "Chapter Reports" > Then click on "November 2002: Advanced Data Driven Design" > There is a link to the presentation at the bottom of the summary > window... Grumble, grumble, grumble. Flash only?? When are people going to realize that a lot of people don't have/want to have/can have Flash installed? Is there a non-Flash link to the presentation? Maybe a direct link? I'd really like to read it. Thanks. --Noel ================================================================================ From: Tom Forsyth (tomf^muckyfoot.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed poo l allocation Date: Thu, 30 Jan 2003 12:44:32 -0000 Horrible innit? I think it's here: http://www.igda.org/sandiego/Advanced_Data_Driven_Design.zip Tom Forsyth - Muckyfoot bloke and Microsoft MVP. This email is the product of your deranged imagination, and does not in any way imply existence of the author. ================================================================================ From: Simon O'Connor (simon^creative)-asylum.co.uk> Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed poo l allocation Date: Thu, 30 Jan 2003 12:53:35 -0000 :o) It seems the actual reports themselves are plain HTML though (once you've navigated through the scrolly flashy interface): http://www.igda.org/sandiego/sandiego_summary_Nov02.htm Simon O'Connor Creative Asylum Limited www.creative-asylum.com ================================================================================ From: "Matt Newport" (matt.newport^nicelycrafted.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 13:16:28 -0000 > Grumble, grumble, grumble. Flash only?? When are people going=20 > to realize that a lot of people don't have/want to have/can=20 > have Flash installed? >=20 > Is there a non-Flash link to the presentation? Maybe a direct=20 > link? I'd really like to read it. Thanks. >=20 >=20 > --Noel http://www.igda.org/sandiego/Advanced_Data_Driven_Design.zip --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.449 / Virus Database: 251 - Release Date: 27/01/2003 =20 ================================================================================ From: Chris Hecker (checker^d6.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 07:52:46 -0800 I re-read this, so I'm re-responding. :) Thatcher Ulrich wrote: > doing your game's type and object system in the programming > language will bring you misery. >Which isn't saying much -- I have yet to see any shipping game's >object system, up close and personal, that *wasn't* a prescription for >some sort of misery, but I'll check out those links. Are you saying that all misery is created equal? I mean, your statement here is kind of implying that no solution is better than any other, so I'm wondering if I'm misinterpreting what you're saying. I think that regardless of whether you use "doomed" or "miserable", data hierarchies are just plain "better" than code hierarchies for full-sized modern games, meaning all games with non-trivial object systems should use them going forward, even given than they require infrastructure you have to write up front. Are you disagreeing with that statement, or were you just protesting my use of the word "doomed" as too extreme? Chris ================================================================================ From: "J. Perkins" (jason^379.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: 30 Jan 2003 08:10:45 -0500 This is a good presentation. Unfortunately, like many of the other threads I have read on this topic, it glosses over the inter-component communication, which I have found to be the most difficult part to get right. The generic response is "use messages", but no one ever seems to explain their message system. If anyone has a success story about a fast, flexible solution I'd really like to hear it! Thanks, Jason 379 On Wed, 2003-01-29 at 19:13, Eric Yiskis wrote: > Ack! I mean't "Chapter Reports" instead of "meeting notes"... Sorry for > spamming the list... > > http://www.igda.org/sandiego/flash_site.html ================================================================================ From: (christer_ericson^playstation.sony.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 10:29:37 -0800 Chris Hecker wrote: >[...] I think that >regardless of whether you use "doomed" or "miserable", data hierarchies are >just plain "better" than code hierarchies for full-sized modern games, >meaning all games with non-trivial object systems should use them going >forward, even given than they require infrastructure you have to write up >front. Okay, I'll be the devil's advocate. Why are they better? Also, how do you define "data hierarchies" and "code hierarchies". Christer Ericson Sony Computer Entertainment, Santa Monica ================================================================================ From: Mark Danks (mdanks^STORMFRONT.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed po ol allocation Date: Thu, 30 Jan 2003 11:16:52 -0800 Potentially, although I haven't looked into Scott Bilas's system that much (time to do some reading). I can describe a bit more about how I am doing it for our next games though... Attributes for objects fall into the "has a" category, instead of the "is a". However, they are typical used for larger constructs, not for every little piece of data. For example, we don't have hit points as an attribute...that is too fine grained for us. We do have attributes like "living creature" which might contain the hit points though, as well as other a number of other stats. The other thing which we do is to have attribute managers. If you want to collide with all objects which are collidable, you don't go through the list of objects looking for the collision attribute, but instead you go to the collision attribute manager and ask for all of the collision attributes (which contain back pointers to the object itself). Being in the console world only, I had a couple of objectives with the system: 1) We don't have to worry about "community addons" (ie, everything is done in-house with access to code) 2) Because of the limited I/D cache sizes, it is important to only access the objects which contain stuff you care about. A lot of searching for attributes and/or calling empty virtual functions sucked up a lot of performance on our last title. Also, because there are managers for the attributes, the managers can call member function pointers (which can be virtual functions) to run code without caring what the actual object is. The tick attribute can contain all of the scheduling/priority info for ticking an object...the manager is the one who actually calls the member function pointer...and the object does whatever it wants to. In answer to your question about resolving what type of attribute you get and how to get one, since an attribute is more than just a float or int (it is a full data structure with functions), the "querying" object needs to know what the attribute is at a code level, and we have a quick RTTI like system to track things down. Later, Mark ============================== = (mdanks^stormfront.com) = Technical Director PS2/XBox = http://www.danks.org/mark ============================== ================================================================================ From: Ray (ray^guildsoftware.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 13:36:13 -0600 J. Perkins wrote: > This is a good presentation. Unfortunately, like many of the other > threads I have read on this topic, it glosses over the inter-component > communication, which I have found to be the most difficult part to get > right. The generic response is "use messages", but no one ever seems to > explain their message system. If anyone has a success story about a > fast, flexible solution I'd really like to hear it! I agree. It was disappointing reading that and it not going into any more detail. But I immediately thought of something like this: All components reference the encapsulation object, and when the component wants to do something, it sends a msg to the object and then the object just routes it to all the components. Simple, but it may work. There's probably a ton of gotchas in that, like the AI component would have to send msgs every frame to the character mesh to walk around or something. - Ray ================================================================================ From: "Igor Kravtchenko" (igor^obrazstudio.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 21:09:21 +0100 > Attributes for objects fall into the "has a" category, instead of the "is a". So typically, instead of making a class' inheritance you nest it as a member ? Igor. ================================================================================ From: Mark Danks (mdanks^STORMFRONT.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed po ol allocation Date: Thu, 30 Jan 2003 12:36:54 -0800 Yes, although attributes can be added/removed on the fly (not always recommended, but possible). Makes it easy for the script system to change the behavior of an object and not require a code recompile. Later, Mark ============================== = (mdanks^stormfront.com) = Technical Director PS2/XBox = http://www.danks.org/mark ============================== ================================================================================ From: "Chris Carollo" (ccarollo^ionstorm.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed po ol allocation Date: Thu, 30 Jan 2003 14:47:00 -0600 > The other thing which we do is to have attribute managers. > If you want to > collide with all objects which are collidable, you don't go > through the list > of objects looking for the collision attribute, but instead > you go to the > collision attribute manager and ask for all of the collision > attributes > (which contain back pointers to the object itself). Another way of structuing this (as we did at LG on Thief) was to have the system be property-major rather than object-major. So you don't actually ask the object whether it has a property, you ask the property whether that it's on an object. So, of course, you can ask it for all objects that a property is on trivially as well. You can also specify different storage types for individual property types, so that certain properties that are really sparse and want fast random access can use a hash (or share a hash), or you can use an array for ultra-fast access at some memory cost, or lists for properties that are iterated over constantly, or whatever. But the nice thing is that it's all per-property-type customizable. Which can be troublesome for things that persistent or streamed-in worlds, because it's tougher to swap objects since their property data is interspersed throughout the properties themselves. On a related note, while it definitely seems like most folks on the list are moving toward this kind of "has-a" relationship for game data and behavior, I haven't heard much about how people are handling data inheritance. Here at Ion Storm (and at LG too), we have a tree of our game objects, and designers are free to add properties at any level of the tree. Some of these properties are instantiated down onto object instances, some aren't (and are thus queried by doing an up-tree search). Which properties are which depends on the intention of the property (instance data like hitpoints wants to live on instances, not up the tree), the frequency at which the property is queried (don't want to do that up- tree search all the time), storage concerns (copying down all the properties to the leaves can mean lots of redundant data), etc. Unsurprisingly, there are issues with this scheme: - What about propreties that change on archetypical objects that already have had their properties instantiated down on object instances? Do they get auto-updated? - What about changes on instances that don't WANT to reflect changes in their archetypes? - What if you want aggregation rather than overriding? - What if you want to override a property by the LACK of a property? - How do you deal with different properties pulling how the tree wants to be organized in different directions? This is the area where I'd really be interested in hearing about what other people have done. Or whether other people have dodged the issues entirely somehow. We've got workable solutions in place, but I really feel there's a lot we could be doing better. -Chris ================================================================================ From: "Charles Cafrelli" (skywise^iquest.net) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 15:58:49 -0500 It appears to me that inheritance definitely gets you into trouble with an open ended object set (like most games will have). But if the object set is known, it can work to your advantage (for instance a GUI object system with well-defined widgets like buttons, edit boxes, etc). I use a little of both in my engine design: I have a basic Object class which inherits from an OOPComm (object messaging system) and a Serializable class. The OOPComm class is java-esque in that you can register for messages from the object, and listen to other objects for other messages. Serializable allows you to stream your data in and out. The Object itself has support classes for factory construction and ObjectList's (each object knows which list its on so that when it's deleted, it will automatically remove itself from all the lists) My View and Model classes each derive from Object. This way models and views can now inherently communicate with each other, and hand off serialization commands to each other (models can create Views of themselves). Object Architectures are then meant to be built on top of the Model class. I have a GUI-Widget set that's very inheritance heavy. (Button, textfields, edit boxes, list boxes, etc, all derive from an Widget class, which is directly derived from Model.) On the other hand, I have a 2D game engine which has only 2 objects derived from Model. A "static" object which is a placeholder for a non-moving graphics object (actually now it'll handle scripted actions, but it doesn't get cross-referenced with the AI, or send out messages), and a "full" object which gets an AI component (err... a script), messaging, user interface and other fun stuff as needed. Although writing this now, I could probably merge both into one object. When you need to handle sets of objects, you setup a container of the object you need (message groups get something like a std::list container, I have one instance where a model loads its views into a std::map for quick lookups.) The views are distinctly separate so I can "plug in" different rendering engines with different view data needs at load time. My 2 cents anyway. ================================================================================ From: "Pierre Terdiman" (p.terdiman^wanadoo.fr) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 22:18:25 +0100 I'd have a naive pragmatic question here. Let's make up an example using multiple inheritance : class SomeEntity : public Renderable, public Collidable, public Controllable, public ; class SomeMesh : public SomeEntity; class SomeClothObject : public SomeMesh; Let's imagine we override a method from Controllable : SomeMesh::MouseDragCallback(...some params...) { // Here I move the mesh on screen, according to the mouse motion } Then the behaviour is customized for cloth objects, so that we actually pull them : SomeClothObject::MouseDragCallback(...some params...) { // Here I move a single vertex of the cloth patch } Ok now the "has-a" alternative would be for example : class SomeEntity { Renderable mRenderable; Collidable mCollidable; Controllable mControllable; mWhatever; }; Now my naive pragmatic question is : how do you "override" things, now ? Are you doing this using the "messaging system" one mentioned ? How, exactly ? I'm not sure how you can do the link (communication) between "mControllable" and "SomeEntity" in a convincing (efficient / handy) way ? Note that I'm eager to learn, I think I've reached the limits of MI, it starts beeing painful.... maybe we should move this to the SWENG list) - Pierre www.codercorner.com PS : eeer, the example above is not what I'm actually doing, in case you wonder :) ================================================================================ From: "Thatcher Ulrich" (tu^tulrich.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 16:18:36 -0500 On Jan 30, 2003 at 07:52 -0800, Chris Hecker wrote: > > Are you saying that all misery is created equal? I mean, your > statement here is kind of implying that no solution is better than > any other, so I'm wondering if I'm misinterpreting what you're > saying. No, I agree some solutions may be less miserable, and therefore worth knowing about and discussing. > I think that regardless of whether you use "doomed" or "miserable", > data hierarchies are just plain "better" than code hierarchies for > full-sized modern games, meaning all games with non-trivial object > systems should use them going forward, even given than they require > infrastructure you have to write up front. Are you disagreeing with > that statement I disagree with that statement. To be a little more concrete, I'm assuming by "code hierarchy" you mean "C++ inheritance", and by "data hierarchy" you mean "some object model implemented explicitly in code, with an emphasis on being data-driven". (If you mean something else, then maybe I don't disagree...) It seems to me that the crucial differences between data hierarchies and code hierarchies boil down to: data hierarchies: * can change object composition without recompiling, and also at run-time * must implement message plumbing and class construction; often hairy and inefficient code hierarchies: * classes fixed at compile time * language support (but dynamic_cast<> is inefficient, and C++ inheritance is hairy) I think different games will weight those factors very differently. Some factors may be a disadvantage in one context, and an advantage in another. So I don't see how you can make the blanket statement that data hierarchies are better. -- Thatcher Ulrich http://tulrich.com ================================================================================ From: "Paul Bleisch" (paulble^microsoft.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 15:41:28 -0600 Generally this is handled through some sort of delegation model. =20 Message passing systems usually make delegation easier to do=20 (i.e ObjectiveC, smalltalk, etc...) but they are not the only=20 method - automatically generating proxy implementations on "outer" classes and such is another approach. From those I've seen/used, most non-vtable based method call=20 interfaces implemented in C/C++ cost something in performance or have some hideous macro/syntax crud. Languages that natively support override/inheritance models different than vtable=20 approaches tend to add semantics/features to the language that afford performance increases. Cecil, Dylan and the general group of multimethod languages come to mind.=20 I believe most multimethod languages (or those supporting predicated=20 dispatch) do some sort of call-point caching and or call-point=20 optimization (predicate trees or some such I think they are called). =20 These types of optimizations generally require whole-program=20 knowledge so you give up some of the run-time dynamic composition=20 for speed. =20 After being really excited about dynamic composition for a long=20 time, I've recently discovered that the end goal was just to have=20 low latency design (no long recompiles) and to support an intuitive=20 "builder" / composition interface. I think both of those are=20 possible without true dynamic composition which simplifies the object model considerably. Paul ================================================================================ From: "J. Perkins" (jason^379.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: 30 Jan 2003 16:44:20 -0500 You have to add the concept of a "behavior", which can be part of the SomeEntity class or a separate attribute itself. It has to catch the "MouseDrag" message (how to do this efficiently? I don't know, I'm hoping someone can clue me in) and perform whatever action is appropriate. By plugging in different behavior attributes, you can get different behaviors (go figure). Of course, using composition doesn't prevent using inheritance, so you could provide some "base" behaviors and then specialize them with derived classes, while still offloading a lot of the other stuff to attributes. This works pretty well, assuming you can figure out the messaging part. Jason 379 On Thu, 2003-01-30 at 16:18, Pierre Terdiman wrote: > Now my naive pragmatic question is : how do you "override" things, now ? Are > you doing this using the "messaging system" one mentioned ? How, exactly ? ================================================================================ From: Mark Danks (mdanks^STORMFRONT.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed po ol allocation Date: Thu, 30 Jan 2003 13:50:13 -0800 The majority of objects are C++ code which then are derived by script objects (think of UnrealScript's extend). This means that sending messages is fairly straight forward through that script system. However, we often do stuff through code as well. In the case with the mouse movement (or joystick in our case :-) you can easily do something like: ClothObject constructor { register member function ClothObject::mousePress with control attribute on press register member function ClothObject::mouseDrag with control attribute on move addControl attribute to manager (and attach to ClothObject) } bool ClothObject::mousePress(some parameters) { // tell the manager we were selected if selected return true else return false } ClothObject :: mouseDrag(some parameters) { // manager is filtering out the drag info based on selection do stuff here } Then whenever the input control manager gets a mouse event, it can go through any object which has registered that attribute. Don't underestimate the power of pointers to member functions. They can be pointers to virtual functions and they will still get resolved correctly at run-time. A bit slower than a normal virtual function call, but we aren't using it for drawing tris :-) Some attributes in the code callback simply call off to the script system ...it is all event driven which can either be queued up or executed immediately, in which case it looks like a function call (assuming that the script system has a handler for it). Hope this all made sense. Later, Mark ============================== = (mdanks^stormfront.com) = Technical Director PS2/XBox = http://www.danks.org/mark ============================== ================================================================================ From: "Kyle Wilson" (kyle^gamearchitect.net) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 16:52:26 -0500 Pierre Terdiman wrote: > Now my naive pragmatic question is : how do you "override" > things, now ? Are > you doing this using the "messaging system" one mentioned ? Well, first of all I think you want Renderable, Collidable, Controllable and so forth to all be derived from some simple Component interface, so instead of class SomeEntity { Renderable mRenderable; Collidable mCollidable; Controllable mControllable; mWhatever; }; you just have class SomeEntity { std::vector mComponents; }; though you may want to cache pointers to individual commonly-accessed components for speed. You wouldn't override mouse drag behavior by overriding a virtual function in code. Instead, you'd assign a particular object a ClothMouseReactor component (or something) in data. How you do that is pretty open, but most component-based game object schemes support inheritance hierarchies in *data*, just not in code. So you might have a ClothThing class represented in XML as descriptors for a parent class, a list of components, and parameters for those components. At runtime that all gets flattened out into the simple container of components I described above. Which is why people keep saying that the open problem is component interactions. :) You can have your ClothMouseReactor component written in script or code, but somehow it's going to need to identify the ClothRenderable component of the same object and communicate force/velocity information to it. Does it look for it by name, or by some kind of component type-identifier? Does it cache a pointer at load time or search every frame? Does it cast and call functions directly, or query for an interface, or just broadcast a message? How do recipients resolve message types? Can variable stacks be bundled with messages? Do messages get sent to all components? If not, how do you identify recipients efficiently? And so forth. Kyle ================================================================================ From: Atman Binstock (ajb^panix.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 17:17:54 -0500 >This is a good presentation. Unfortunately, like many of the other >threads I have read on this topic, it glosses over the inter-component >communication, which I have found to be the most difficult part to get >right. The generic response is "use messages", but no one ever seems to >explain their message system. That's because they all suck. You can pretend you don't have "messages" and simply do a lot of dynamic type/composition discovery to pick apart your "target" object and directly manipulate it. Or you can do messages... Start with taking your pick of any of the things people have been talking about for object representation and use it for your message. Then add some code to your message. Then figure out how you are going to route messages and you are mostly there. On one extreme is simple objects and complex messages. Messages can have free form data and code. Target objects route messages (and sub-messages) to their components. It can become a plumbing nightmare... On the other extreme is simple messages (just a message type and some params) and complex objects. The target object interprets the message. This is just the OO object model (ex: a virtual member function call). Note that the same crap is still going on, just differently. Ex: in C++ the message types are statically fixed and the "routing" happens in the fixed object code, eased by having all the members (and their types) statically available. --- You can look at it as a matrix of message vs target object... If this all sounds familiar, it's because it's something like the age old software engineering question of where's the data and where's the code.... This is a hard problem. Repeat after me: there is no silver bullet. Some important topics: Where is the code for objects? Where is the glue code between objects? Is there a difference? Is the code in a script system (god help me)? How far do you stray from the C++ object model? I.e. how much dynanicism do you need? And How much are you willing to pay for (in run-time speed/size, dev effort, debugability, etc)? How does the system work in the studio? Who writes game code? Who debugs it? How is it versioned? --- Some recurring patterns from systems I've written or seen (tending on the OO code hierarchy side): Smart pointers/object id's: for safe access despite unknown object lifetimes. Introspection for both editing and persistence. It's not the fastest for loading, but can be optimized. It also needs to be smart to respect constraints between values. Scene graphs: spatial parenting is natural for games. Trading "is-a" for "has-a" when you do want to override behavior is a mistake. Lots of MI of narrow interfaces for interaction. Optimization requires customized interaction managers (spatial hierarchies etc). "Final config" options that make vastly different tradeoffs. For ex: compiling to code and re-linking. Atman Binstock (ajb^panix.com) ================================================================================ From: Chris Hecker (checker^d6.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 14:15:55 -0800 >Okay, I'll be the devil's advocate. Why are they better? Also, >how do you define "data hierarchies" and "code hierarchies". Well, a bunch of these issues have been talked about before, so I'll give quick responses without much explanation. Feel free to protest any claim in your role as DA. I'm really just repeating the intro to the various talks that have been posted. First, the domain I'm talking about is games with lots of heterogenous objects that have gameplay characteristics (not just different meshes, etc.). I think this covers most modern games on both consoles and PCs, hence the earlier sweeping claim. "Better" is defined as being easier to iterate the design during development, and easier for non-programming designers to experiment with ideas that affect gameplay. So, this means things like not needing to recompile the game to change whether an object does damage when it hits you, or changing doors to be able to have hitpoints and catch on fire, etc. It doesn't mean that the entire game is somehow data-based, or that no code ever needs to be written. Behaviors take code, but assigning behaviors shouldn't require code changes in all cases. Non-algorithmic changes shouldn't require touching the game code or hopefully even the scripting language. Just like an object's hitpoints value makes sense to datadrive (as opposed to hard coding 75hp into the source), whether an object has hitpoints in the first place makes sense to datadrive. "Code hierarchy" means having the type system in your game encoded in the programming language's type system, usually in C++ classes for this discussion. "Data hierarchy" means that types are encoded in data explicitly stored in memory, so you load/save it, introspect on it, change it around at runtime, add and remove data from types and objects, etc. There are hybrids, but I'm really talking about taking it to the extreme where all objects in the game code are just IDs, and the entirety of their type information is stored in data structures. Given my definition of "better", coding game types and objects in C++ is doomed past a certain level of complexity and/or number of developers because the C++ type system is simultaneously too lightweight and too heavyweight to express an object system design and have it be iteratable easily, especially by non-programming designers. Code type hierarchies do not do mixin very well (this object is Flamable, Breakable, Boyant, HasAFlockingBrain, etc.), and that goes double for C++. If the types of objects are coded in the game source, then you have to recompile it to change the types, and if the object properties are part of the type (which they are for any reasonable definition of "type", I think) then adding or removing properties is a recompile, let alone being able to be accomplished at runtime (I throw gasoline on an object, making it Flammable where it wasn't before, etc.). Most games are hybrids between code and data type hierarchies, even if they don't recognize it. As soon as you decide to not have a separate C++ type for each monster, and just have a type flag in the Monster class, or put a hash into your base Object type to store random heterogeneous information, or members start floating up into your base class even if they don't make sense for all objects, you've started down the road. My point is just to go all the way down that road and data-drive the whole shebang, and you get a lot of benefits. One interesting discussion to have is whether behavior is per-object or per-property. Thief is the latter, Dungeon Siege is the former (generally). There are game design ramifications to the choice. Do you want a more simulation-y emergent environment, or a more unique-y authored environment? Do all objects that are OnFire act the same so there's consistency, or do they all have different behaviors so there's variety? This is a good example of where a technical decision hugely impacts the design space. Chris ================================================================================ From: Chris Hecker (checker^d6.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 14:33:57 -0800 >So I don't see how you can make the blanket statement that >data hierarchies are better. This is the internet...if a guy can't make blatant unsupported generalizations here, where can he? >I think different games will weight those factors very differently. >Some factors may be a disadvantage in one context, and an advantage in >another. Boring balanced thoughtful engineering-speak! :) No, but seriously, my latest reply to Christer's devil's advocacy described the domain in which I feel like my blanket statement is at least "mostly valid" (ie. games with large-scale heterogeneous object systems that affect gameplay). As is usual in the real world, hybrids will probably be the most popular, but to say another somewhat blanket generalization, I think the extreme of data-hierarchies is actually interesting (only basic types like float and int as in-code types, everything higher level is data-composed), while the extreme of code-hierarchies is totally noninteresting and doesn't work at all (different C++ classes for each monster, or trying real mixin with C++ inheritance, or really extremely hard coding hp directly into the type, for example). Chris ================================================================================ From: "Igor Kravtchenko" (igor^obrazstudio.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 23:57:16 +0100 This thread seems to me quite fuzzy. I have to admit I like to have logical and pragmatic thread. If the conclusion would be to avoid to massively use inheritance, the answer is obviously ... yes ! Too many inheritance, as many of you said, break the logical of the classes tree. Personally I would never even inherit a mesh from a Skinnable thing. Why ? Because inheritance, from my personal point of view, need not to be used to include features in a lazy way. So, in this case, yes : class Mesh { Skin skin_; }; That's also very usual in Java where MI is not available. Same goes for engine which has SpotLight, PointLight, DistantLight, etc... all inherited from a Light's class which has itself almost nothing as members. Unnecessary. That said, for all the other things which can be modified in a manner or another, I don't see any rigurous argument to avoid virtual methods (thus, inheritance). Typically, I only see two methods to include behaviors : - inheritance as said with methods overriding (1) - registering of callback functions through a third-party interface with user data (2) (1) requires special allocation to match with the class instance but has the advantage to precisely have an optimised memory layout in one "block" only which exactly fits with your needs (2) allow to attach/detach any behaviors on the fly without any re-instanciation. You just take "contol" of an object on the fly. In theory I would tend to prefer (2) but in practice if you don't concretly have the need for, (1) is (I feel) more easy to set up. However, (1) needs to have some sort of TYPE enum at instanciation whereas (2) don't. You allocate your object and manipulate it later by separately importing behaviors. This can be also achieved by subclassing but is then, extremely much less comfortable. Just a matter of needs, as usual. Igor. ================================================================================ From: "Igor Kravtchenko" (igor^obrazstudio.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Fri, 31 Jan 2003 01:22:38 +0100 > class SomeEntity > { > Renderable mRenderable; > Collidable mCollidable; > Controllable mControllable; > mWhatever; > }; This would be rather : class SomeEntity { Renderable *mRenderable; Collidable *mCollidable; Controllable *mControllable; *mWhatever; }; with the corresponding Get/Set wrapper. Each of them would have to inherit from a common Behavior class. Igor. ================================================================================ From: (phil_wilkins^playstation.sony.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 16:38:02 -0800 Chris Hecker (checker^d6.com): > Boring balanced thoughtful engineering-speak! That gets games written. >:) ;p > I think the extreme of data-hierarchies is actually interesting (only basic types like float and int as in-code types, everything higher level is data-composed), Only in sense that languages like Smalltalk are 'interesting'. As in, I'm interested in watching other people try this, watching them fuck up, then take the things that worked, and dump the stuff that doesn't. I'm incredibly skeptical that a pure/extreme approach is actually going to be practical, and I certainly wouldn't bet anything of value on it. Cheers, Phil ================================================================================ From: (christer_ericson^playstation.sony.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 17:01:01 -0800 I think there is a wide spectrum of informal definitions of what 'data driven' means. On the far left is a very pragmatic definition simply saying that the engine is data driven if it allows artists and designers to do various things without programmer intervention. On the far right is the everything-is-polymorphic-and-everything- can-be-anything engine, all controlled from a data file written out by the tools. The latter seems to be something that appeals to techy people just because it is flashy and a programming challenge. It is certainly what gets discussed in various incantations again and again. You easily get the idea that everyone thinks that data-drivenness in absurdum is 'da bomb' and that it is the only way to go. You don't see many people arguing for the left side of the scale -- so, I thought I'd stick my neck out and do just that. My personal opinion, based on some experience and possible biased by a streak of old-schoolism, is that the right-hand side view is overengineering. It makes your typical game oh so much more complicated, with rather unclear benefits. Do they really end up using all these advanced features? (No.) Is it really worth spending all that time on something they're not using? (No.) In the end, is it really buying you something that you wouldn't have been able to accomplish with a simpler system? (No.) FYI, we have an engine where even the order of our various server subsystems (animation, rendering, scripts, etc) is controlled from a data file. If no animation system is connected from the data file, then by golly, there won't be an animation system running in the engine. If you want the scripts to run after rendering, you specify this through the data file. This means we can't even run our engine without a data file to initialize it, creating the hierarchy of servers that you'll run the game on. Does this really buy us anything? Of course not. Does it complicate the debugging? You betcha. Did we get carried away? Yes. Should we rip it out? Absolutely. It's not something I lose sleep over, but the more I see and, perhaps, the older I get, I find the thought of hardline data- drivenness less and less appealing and I'm turning more and more left on the scale. Presumably the truth is somewhere in-between. But no one is advocating that either. It's still not techy, flashy, cool stuff -- it's just pragmatical and what gets your game done. I guess I'm ranting, so I'll shut up now. Christer Ericson Sony Computer Entertainment, Santa Monica ================================================================================ From: "Thatcher Ulrich" (tu^tulrich.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 20:24:56 -0500 On Jan 30, 2003 at 02:15 -0800, Chris Hecker wrote: > > "Better" is defined as being easier to iterate the design during > development, and easier for non-programming designers to experiment with > ideas that affect gameplay. So, this means things like not needing to > recompile the game to change whether an object does damage when it hits > you, or changing doors to be able to have hitpoints and catch on fire, > etc. It doesn't mean that the entire game is somehow data-based, or that > no code ever needs to be written. Behaviors take code, but assigning > behaviors shouldn't require code changes in all cases. Non-algorithmic > changes shouldn't require touching the game code or hopefully even the > scripting language. Just like an object's hitpoints value makes sense to > datadrive (as opposed to hard coding 75hp into the source), whether an > object has hitpoints in the first place makes sense to datadrive. Bah! That's the worst definition of "better" I've ever heard . The problem is that it says nothing about the outputs that matter How about: "Better" means you ship a better game, spend less money/time in development, and/or endure less misery in the process. Now, if you presuppose that "data hierarchy" designs produce better games with less money and misery, because it lets you have spontaneously flaming doors without a recompile, then the rest of your argument follows. But if there are tradeoffs involved in building a "data hierarchy", and there are, then you need to consider the holistic effects on the overall production of the game. Often what seems worse is actually better. Anyway, I see that Christer gave a much "better" answer, so I'll stop now and just say amen to his post... -- Thatcher Ulrich http://tulrich.com ================================================================================ From: Charles Bloom (cbloom^cbloom.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 17:44:59 -0800 At 05:01 PM 1/30/2003 -0800, (christer_ericson^playstation.sony.com) wrote: >I think there is a wide spectrum of informal definitions of what >'data driven' means. [... good message ...] Christer is correct. The "data driven" school has become a bit of a religion, founded on perhaps a single success story (Dungeon Siege) in the entire history of data-driven games (small exageration). Completely data driven = pointless, disaster Somewhat configurable by designers = good Also, remember the rule that the more the designers can data-drive the game, the more ways they can break it. Our current game is mildly data-driven, in that the designers cannot create new "concrete types" with data, but they can control a lot of parameters. Still, they manage to break the game all the time. Another rule is : more specific behavior = easier to write & maintain, faster, etc. , so making modules that are generic enough to really work in a data-driven system means that those modules will take many fold more hours to write and maintain. I want code systems that do their specific job and that always work, that designers can't screw up. ------------------------------------------------------- Charles Bloom (cb^cbloom.com) http://www.cbloom.com ================================================================================ From: Mark Danks (mdanks^STORMFRONT.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed p ool allocation Date: Thu, 30 Jan 2003 18:10:17 -0800 I completely agree with Christer and Charles. A "middle-ground" is definitely what we are going for. In fact, all of this "data-driven" stuff that we have done is mainly for the programmers, not for the designers. As an example, no designer at Stormfront writes actual scripts. We have a level editor which connects all of the object scripts together, sets parameters, machine generates the real game scripts, etc. But if you want to make a new script, we have only exposed both how to do it and the actual language to the programmers. However, the designers and artists have a ton of little tools which they can piece together in ways we never expected, and most of the time it doesn't require a programmer. In general, if they have done something before, it shouldn't require a programmer to do it again (like add a new character and assign a basic behavior set). Considering that I have rewritten the object hierarchy ever time a project starts up, I have learned that making something to last forever just isn't that useful :-) Later, Mark ============================== = (mdanks^stormfront.com) = Technical Director PS2/XBox = http://www.danks.org/mark ============================== ================================================================================ From: "Jon Watte" (hplus^mindcontrol.org) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Thu, 30 Jan 2003 20:25:48 -0800 > I'm really interested in hearing how other teams are handling this shift > before Noel and I start redesigning our game object system later Our product is entirely based on factories that return interfaces, and comcrete implementation objects multiply derive from many interfaces, and aren't usually references as the concrete class outside their definition (which means most concrete class declarations actually live at the top of the .cpp file). Cheers, / h+ ================================================================================ From: Chris Hecker (checker^d6.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Fri, 31 Jan 2003 02:21:28 -0800 >Bah! That's the worst definition of "better" I've ever heard ><...> >"Better" means you ship a better game, spend less money/time in >development, and/or endure less misery in the process. Hey, at least I didn't use the word I was defining in its definition. :) Anyway, I'm actually not saying everybody should overdesign an incredibly byzantine delicate monstrosity for the sake of doing it, as surprising as that may sound. I'm also not saying you should take it completely to the data-driven extreme of only basic types in code (although I did say I think that is interesting from a research/theory standpoint, as opposed to the other extreme, which has been tried and proven to not work over and over again by everybody who ever read an OOP book and got their hands on a C++ compiler). Of course you can carry things too far, in either direction. Of course you can make mistakes and waste work when you don't have your eye on shipping the game. Of course you want to use good engineering judgement when designing and implementing. Like, duh. To be clear, I claim that something along the lines of the Thief system outlined in that ObjSys.ppt is the right direction to be heading for the kind of rich-world games that I am talking about. It's not about trying to write the uber-simulator of all time, and it's not a case of "founded on perhaps a single success story" at all, it's been a bunch of games (Thief, Dungeon Siege, Deus Ex, and System Shock 2 at least, and Halo from what I've read here) that are trying to push boundaries in terms of optimizing the design process, encourage iteration, and empower designers to actually do their jobs, which is design the gameplay. If "designer" to you is a drone who should only be tuning damage numbers on fixed types and placing prebuilt monsters, and begging programmers for anything more than that, then obviously this type of system isn't for you. However, I don't think that's the best way to get much interesting new gameplay moving forward. Time will tell! Chris ================================================================================ From: Wayne Coles (wcoles^reflectionsinteractive.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed poo l allocation Date: Fri, 31 Jan 2003 12:19:54 -0000 A quick think on this has led me to the following, maybe I'm missing something (I haven't thought about it for long) but it seems to be an inordinate amount of indirection going on.... enum kAttributeType { kFloatAttribute, kIntAttibute, // Extend for all supported attribute types... }; union ATTRIBUTE { int iValue; float fValue; // Extend for all supported attribute types... }; struct Attribute { String name; kAttributeType type; ATTRIBUTE value; }; class Object { private: AttributeList m_Attributes; ComponentList m_Components; public: Object(); ~Object(); // We're not a base class bool GetAttribute( const String &name, IntAttribute &attribute ); bool GetAttribute( const String &name, FloatAttribute &attribute ); // Extend for all supported attribute types... }; class Component { friend class Factory; private: Object *m_pOwner; // Initialised by 'Factory' public: Component(); virtual ~Component(); virtual bool Initialize(); inline Object& GetObject() const { return *m_pOwner; } // Helper methods, that call m_pOwner->GetAttribute... inline bool GetAttribute( .. ) }; class FloatAttribute { private: Attribute *m_pAttribute public: FloatAttribute(); FloatAttribute( Attribute &attribute ); FloatAttribute( const FloatAttribute &other ); ~FloatAttribute(); FloatAttribute& operator=( Attribute &attribute ); FloatAttribute& operator=( const FloatAttribute &other ); inline float GetValue() const { return *m_pAttribute; } inline void SetValue( float fValue ) { m_pAttribute[ 0 ] = fValue; } inline const String& GetName() const { .. } }; // Similar classes for other attributes... Probably templates can be used to reduce some repetition, I haven't thought that deeply yet. Using the above allows components to query their parent object for certain attributes only during the final stages of object construction, once found, they can use the local helper class to mediate 'type-safe' access to components. class Example : public Component { private: FloatAttribute m_Health; Public: bool Initialize() { if ( GetAttribute( "Health", m_Health ) ) { // m_Health.GetValue() is now valid return true; } return false; // Object creation fails } } We can return a reference from 'GetObject' as the system guarantees that no method will be called before the pointer has been set (apart from the constructor). I've not included any messaging as I haven't thought about that part yet. Apologies for the amount of code in this mail, it came out longer than I'd thought. I also can't be sure if this is similar to other implementations. It looks interesting, using the 'attributes' in the above example allows components to share them, but they're non-local data accesses so it may not be friendly for those machines with small cache sizes. I'm not so fond of the fixed set of 'attributes' in the example, which kind of clamps down on what you can do. However, I'm not sure how you can do this otherwise, in a type-safe way? Anyway I'd better shut-up before ... oh too late... Wayney -Virus scanned and cleared ok ================================================================================ From: Noel Llopis (llopis^comcast.net) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed poo l allocation Date: Fri, 31 Jan 2003 08:04:59 -0500 On Fri, 31 Jan 2003 12:19:54 +0000 Wayne Coles (wcoles^reflectionsinteractive.com) wrote: [...huge snip...] > I'm not so fond of the fixed set of 'attributes' in the example, which kind > of clamps down on what you can do. However, I'm not sure how you can do this > otherwise, in a type-safe way? I'm not really sure what you're accomplishing with all that level of indirection. It looks more like a system to do serialization than anything else. Personally, I see each component as something very self-contained, written in C++ or in a script language without exposing any of it internal variables. The data in a component is hardwired and up to the component. So, in your example, I think you were trying to create a component that keeps track of the health of a unit, right? Here's a higher-level overview of how I see a system like that working. The unit doesn't even know it has "health" or "armor" or anything. class Armor : public Component { //... }; Now your health component will listen to messages that could affect the entities health/damage values. The armor component can be very simple and just subtract (or add) health, or it can be more complex modeling body parts, different types of damage, etc. Whenever the health status changes, it sends a message to the entity with the new status. The entity should also have a damage model component. It listes to health message changes and reacts accordingly. The simples one will simply cause the object to switch to its destroyed state whenever health reaches zero, but it can reduce the speed as health goes down, force limping, or show some progressive damage. Now designers have two types of components: Armor and DamageModel. In practice you'll probably have several variants of each type of component (ArmorSimple, ArmorBody, etc). Each type of component exposes some varaibles that can be tweaked from the tools (amount of damage between transitions, damage table, etc). By default, game entities don't have either one of these components. But now somebody can choose to create a new type of door, add a simple armor and damage model components to it and place it in the world. Automatically, shooting at that door or running into it with a vehicle (or anything that will cause damage) will make it blow up and let the player through. Depending on your game, it might make sense to combine the two components into one (if they each are relatively simple) to help with performance a bit, but the same principle applies in that compoents just listen to messages, and send messages back. Gosh, I hope this made some sense and it was related to what you were asking. I'm starting to have my doubts ;-) --Noel ================================================================================ From: Wayne Coles (wcoles^reflectionsinteractive.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed poo l allocation Date: Fri, 31 Jan 2003 14:27:52 -0000 > I'm not really sure what you're accomplishing with all that level of > indirection. It looks more like a system to do serialization than > anything else. Yeh, it was basically sharing certain attributes that would be used between components (like position, orientation, whatever.. :). Where attributes were defined 'externally' as well as which components were used. > Personally, I see each component as something very self-contained, > written in C++ or in a script language without exposing any of it > internal variables. The data in a component is hardwired and up to > the component. This is how I'd usually see it. In my example, I meant that components could still have local member variables. It'd just be shared variables [attributes] that were indirected. > Whenever the health status changes, it sends a message to the entity > with the new status. But now the 'message passing' would be slower than the indirection of the attribute? As the message handling I've seen, you have a virtual 'OnMessage' method, which gets overridden. And each override has its own switch statement and passes unhandled messages up the class hierarchy? I suppose you could 'observe' attributes with my example, but that leads to more indirection (I don't think I'll go there). > Each type of component exposes some variables that can be tweaked > from the tools (amount of damage between transitions, damage table, etc). Right, I think this is what I meant by attributes. You have a 'definition schema' like: Component Damage Float attribute Health EndComponent Object Door uses damage { health = 50; } uses explode { } EndObject So the damage component allows the designer to modify the health (or 'starting health'). The damage component maintains it and fires off the 'destroy' message which is received by the explode component. This isn't very well defined, 'cause I haven't thought it all the way through yet. I think I'm missing something :) This doesn't really show why you'd want to expose the 'health' attribute either, what if it was a 'Man' object, and there was a 'movement' component it might want to alter the movement as the health decreases also? > Gosh, I hope this made some sense and it was related to what you were > asking. I'm starting to have my doubts ;-) It certainly made sense, I'm just not sure if I am, maybe I'm just worrying too much about the PS2... I'm not having a good day :/ Wayney -Virus scanned and cleared ok ================================================================================ From: "Gribb, Gil" (ggribb^ravensoft.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixedpool allocation [bcc][fake adr] Date: Fri, 31 Jan 2003 08:46:41 -0600 I agree with what Charles is saying below. To me, emergent behavior emergent bug. And it also becomes hard to predict the consequences of minor code changes. Elimination of one emergent bug could easily create several new ones. If designers are doing "cool new things that the programmers hadn't thought of", then it is likely many of the things designers are doing won't work under code maintence. I don't really see the market clamoring for emergent behavior in general. -Gil At 05:01 PM 1/30/2003 -0800, (christer_ericson^playstation.sony.com) wrote: >I think there is a wide spectrum of informal definitions of what >'data driven' means. [... good message ...] Christer is correct. The "data driven" school has become a bit of a religion, founded on perhaps a single success story (Dungeon Siege) in the entire history of data-driven games (small exageration). Completely data driven = pointless, disaster Somewhat configurable by designers = good Also, remember the rule that the more the designers can data-drive the game, the more ways they can break it. Our current game is mildly data-driven, in that the designers cannot create new "concrete types" with data, but they can control a lot of parameters. Still, they manage to break the game all the time. Another rule is : more specific behavior = easier to write & maintain, faster, etc. , so making modules that are generic enough to really work in a data-driven system means that those modules will take many fold more hours to write and maintain. I want code systems that do their specific job and that always work, that designers can't screw up. ------------------------------------------------------- Charles Bloom (cb^cbloom.com) http://www.cbloom.com ================================================================================ From: Sylvain Vignaud (vignsyl^iit.edu) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Fri, 31 Jan 2003 11:04:03 +0100 > I think there is a wide spectrum of informal definitions of what > 'data driven' means. On the far left is a very pragmatic definition > simply saying that the engine is data driven if it allows artists > and designers to do various things without programmer intervention. > On the far right is the everything-is-polymorphic-and-everything- > can-be-anything engine, all controlled from a data file written > out by the tools. [SNIP] I totally agree. I don't see the point in too much data driven coding. At the end, I'm the one that will have to write the script, the designers & graphists only now how to write word/excel files and email ;) In my small RTS, I use little still enough data-driven coding. A unit is basically something like: class unit { 3Dmesh *mesh; //3D object in the 3D engine, for position, rotation... UnitKind *kind //Shared properties SomeCopyOfProperties //Shared properties that may be altered by magic }; Some text scripts (I'll have to change this to bin files in order to prevent cheating ;) set up how 3ds file animations are used, and smalll part of behaviour through a very simple condition language (ie: a factory cannot cancel a construction if its unit is already done and the doors are opening to make it go out). I have no use in going further in data-driven coding. ================================================================================ From: Mike Shaver (shaver^off.net) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Fri, 31 Jan 2003 12:08:02 -0500 On Jan 30, Charles Bloom wrote: > Also, remember the rule that the more the designers can data-drive the game, > the more ways they can break it. Our current game is mildly data-driven, > in that the designers cannot create new "concrete types" with data, but they > can control a lot of parameters. Still, they manage to break the game all > the time. This is something I wanted to ask a month ago, but now there's an even better context for it: are there any tools or best practices for doing _any_ sort of static analysis on a data-driven game? It seems like you give up a lot of strong C++ type information, and I wonder how you go about making sure that doors are only ever put on vehicles and buildings, and don't show up as the barrel of a rifle. Or are people not generally using the C++ type information at all, in favour of a more flexible architecture? If everything's an Object, it might as well be void *s and punned integers all the way around, right? =) Mike ================================================================================ From: Mark Danks (mdanks^STORMFRONT.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixedpool allocation Date: Fri, 31 Jan 2003 09:21:41 -0800 For the most part, I agree with this...except the "cool new things that the programmers hadn't thought of" part. I think it depends on what the cool new things are, admittedly a slippery slope. For example, we tend to have a ton of different objects which the designers can place, but they are all really small and don't do much by themselves. The assumption is that it will take multiple objects to accomplish their task, as opposed to one uber-one which the programmers hand down from on high. The key to the programmers sanity is that the objects are very concrete. Each object just does its thing without a lot of individual flexibility. The designer's flexibility comes in hooking them together. Changing how one particular object might break things, but it is very isolated (in that there don't tend to be ripples out to other systems). I guess my point is that if the designers don't have the flexibility to do unexpected things, then the programmers have effectively become the game designers...shudder... Later, Mark ============================== = (mdanks^stormfront.com) = Technical Director PS2/XBox = http://www.danks.org/mark ============================== ================================================================================ From: "Chris Carollo" (ccarollo^ionstorm.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed poo l allocation Date: Fri, 31 Jan 2003 11:35:15 -0600 > At 05:01 PM 1/30/2003 -0800, > (christer_ericson^playstation.sony.com) wrote: > >I think there is a wide spectrum of informal definitions of what > >'data driven' means. [... good message ...] > > Christer is correct. The "data driven" school has become a bit of a > religion, founded on perhaps a single success story (Dungeon Siege) in > the entire history of data-driven games (small exageration). I'd add Thief, Thief 2, and System Shock 2 to that list. And Deus Ex 2, since it seems to be working well for us so far. > Completely data driven = pointless, disaster > Somewhat configurable by designers = good Well, it's obvious that it's a line drawing issue, and the appropriate place for that line to be drawn is different for different games. > Also, remember the rule that the more the designers can > data-drive the game, > the more ways they can break it. True, though it also means that they can fix any data bugs much more quickly because they're not waiting around for programmers to fix them in code and release a new build to them. > Another rule is : more specific behavior = easier to write & > maintain, faster, > etc. , so making modules that are generic enough to really > work in a data-driven > system means that those modules will take many fold more > hours to write and > maintain. I guess I don't see data-driven design being at odds with "specific behavior". It's just that the granularity of the specific behaviors are much smaller than they would be in a more code-driven design. In my experience, the only part of the systems that is "generic" is that behaviors need to be generically (within some scope) applicable, which tends to not be a big deal. If I'm supporting AIs being hit with stimuli, supporting all objects being hit with stimuli isn't a big deal. > I want code systems that do their specific job and that > always work, that > designers can't screw up. I really do think it's largely a granularity issue. At some level, the programming language itself is the finest granularity, and all data in code is the coarsest. Though it sounds like we're more "data-driven" than you are, I think your statement applies to our game as well, though perhaps on smaller individual systems. We've given our designers a lot of power on DX2 -- they can create new object archetypes, attach properties to them, create links between objects that define their relationships, etc. We've given them a form-based condition/action trigger system that can catch game events, query game systems, and perform specific actions. And of course there are many associated gameplay system managers. Each of these systems is small and focused, and does one thing solidly, and the designers were given the tools to interact with them. So far it's been working out very well. Though we're overseeing their work from a technical "crack-checking" perspective, the designers only really need to come to programmers when they want a new specific behavior or feature. Otherwise they can assemble objects pretty much on their end, as well as tune them. Getting that workflow cycle as efficient and simple as possible has been a huge win so far. I don't remember who it was that said that the market wasn't clamoring for emergent behavior, I'd put GTA3 as a pretty strong argument to the contrary. -Chris ================================================================================ From: "Chris Carollo" (ccarollo^ionstorm.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed poo l allocation Date: Fri, 31 Jan 2003 11:40:18 -0600 > This is something I wanted to ask a month ago, but now there's an even > better context for it: are there any tools or best practices for doing > _any_ sort of static analysis on a data-driven game? It > seems like you > give up a lot of strong C++ type information, and I wonder how you go > about making sure that doors are only ever put on vehicles and > buildings, and don't show up as the barrel of a rifle. We have on DX2 (okay, "have" is perhaps an overstatement, "intend to write" is probably more accurate, though we did have one for Thief) a report function rig that allows us to run static analyses of various parts of our game. Specific levels, the object archetype tree, etc. Plus you can use it for things beyond error checking, for asking questions like "what's the loot distribution on this map", or what have you. It's not perfect, as it requires diligence both in running and generation of the report functions, but it was super-useful on Thief. -Chris ================================================================================ From: Troy Gilbert (TroyG^csl.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixedpool allocation [bcc][fake adr] Date: Fri, 31 Jan 2003 17:41:02 -0000 "I don't really see the market clamoring for emergent behavior in general." I would completely disagree with this sentiment. I would argue that the market needs emergent behavior (or more specifically emergent gameplay) to really grow beyond the standard video game mold. If you look at some of the most successful games of recent: The Sims, Deus Ex, Grand Theft Auto III/Vice City. To me, all of these games demonstrate emergent gameplay which is a side-effect (or a direct reaction to) emergent behavior. The power of data-driven games (as they've been discussed in this thread) is their ability for unexpected game mechanics to be employed by the player (whether it's to solve problems or for their own enjoyment). Emergent behavior is very representative of the real world, and from all of my experience it is the best/easiest/quickest way to model complex systems (and I don't think I'm alone on that opinion). Troy Developer Relations Criterion Software www.csl.com ================================================================================ From: Peter Cowderoy (psycho^petercowderoy.org) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Fri, 31 Jan 2003 18:23:12 +0000 (GMT Standard Time) On Fri, 31 Jan 2003, Mike Shaver wrote: > This is something I wanted to ask a month ago, but now there's an even > better context for it: are there any tools or best practices for doing > _any_ sort of static analysis on a data-driven game? It seems like you > give up a lot of strong C++ type information, and I wonder how you go > about making sure that doors are only ever put on vehicles and > buildings, and don't show up as the barrel of a rifle. > Roll your own type system. If the behaviours are in C++ code this really isn't too hard at all, as you're already mapping data to existing classes pretty directly - you just need to assign types to attributes and run a check. Single inheritance is fairly easy to implement, and multiple's not too much harder if you're only doing type checking rather than solving the dispatch problems. If all the types are external then things get a little more awkward, but not much so - you're already having to handle lists of attributes, you just need a definition for each class present in the data files somewhere that gives its own type and the types of attributes you're bothered about having type-checking for. Unless I'm missing something major? -- (psycho^petercowderoy.org) ================================================================================ From: "Igor Kravtchenko" (igor^obrazstudio.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed poo l allocation Date: Fri, 31 Jan 2003 19:27:25 +0100 You talk about notification and message through "elements". In practice, why not merely register some "notification" functions to your behavioral component ? Like a kind of dynamic Vtable. You could then attach/dettach any of them on the fly and expose parameters to the designer through some configure() method on that linked third-party interface. The notified part of your component could also easily send back message to the "notifier" as you suggested. No inheritance or rigid design (if I have well understand your idea). Kewlio ! But would that really be a "new" thing from the history of code design ? I don't think. :) Igor. ================================================================================ From: (christer_ericson^playstation.sony.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixedpool allocation [bcc][fake adr] Date: Fri, 31 Jan 2003 10:27:47 -0800 Troy Gilbert wrote: >[...] >The power of data-driven games (as they've been discussed in this thread) is >their ability for unexpected game mechanics to be employed by the player >(whether it's to solve problems or for their own enjoyment). Please don't link emergent behavior with data-drivenness. They are two completely different things. You can _obviously_ have emergent behavior with code that is completely hardwired. Christer Ericson Sony Computer Entertainment, Santa Monica ================================================================================ From: "Igor Kravtchenko" (igor^obrazstudio.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Fri, 31 Jan 2003 19:27:23 +0100 We use what we call OCP (Ozos Convertion Projection) files. OCP are transparent and automatically generated by our tools when the designer changes any parameters whatever under the editor or his 3D Software (LW, 3DS, etc...). In OCP we store in a ASCII format, the most important informations of the datas he's likely to use in the game. Everything stays in a very abstract mini-script format, easily editable but filled of IDs, name, version and security attributes. When it makes a mistake, change a component in the scene, delete some items, etc... or merely if we choose to change our own format (even with a IFF-chunk based format, it happens to break backward compatibility when major changes are done) the OCP is still here. At reload's time, it recovers all lost informations, re-attach triggers and scripts, re-initialise special properties you may have done before (a 3d sound linked to an object, a trigger to open doors as you suggested, etc...), but also re-import needed resource, re-initialise your shaders, etc... etc... It stays so general that it's almost not breakable itself. Even in worst case, we can re-edit its content in a pretty intuitive way. We can also run some (basic for the moment) statistics on OCP to grab informations. To conclude, OCP are global, general and abstract files which, at any time, save the status of your files' contents and environement to instantly recover lost or breaked informations or merely setup world's statistics. At release, OCP gone. Igor. ================================================================================ From: Mike Shaver (shaver^off.net) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Fri, 31 Jan 2003 13:35:10 -0500 On Jan 31, Peter Cowderoy wrote: > Roll your own type system. Well, types are part of it, but I guess I'm thinking more of something along the lines of an XML/SGML DTD validation process. I mean, a lot of my attributes of type "string", but it might be the case that there are only a handful of legal values, and even if I rolled a really rich type system by hand, it might be the case that it's context-dependent. (A person can be contained within a vehicle, but not a vehicle that's got a state attribute of "destroyed".) Clearly, C++ alone doesn't give you all of this, and my example isn't a great one because it's reasonable to believe that the containment relationship and the vehicle state can both be altered dynamically. So even in a "code-driven" system there's room for love here. And if you can validate these constraints statically, then you're a lot closer to being able to automate the dynamic validation within your game. Mike ================================================================================ From: Troy Gilbert (TroyG^csl.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixedpool allocation [bcc][fake adr] Date: Fri, 31 Jan 2003 18:38:18 -0000 Excellent point, and you're right, they aren't attached at the hip. I guess data-driven design helps the *designers* create emergently, as opposed to hardwire? So, perhaps I should reword it as "The power of a data-driven architecture is the opportunity for unexpected game mechanics to result from emergent *design*." But of course, don't take this as a blanket statement to any degree... just my thoughts on the subject. ;) Troy Developer Relations Criterion Software www.csl.com ================================================================================ From: "Paul Bleisch" (paulble^microsoft.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Fri, 31 Jan 2003 12:43:33 -0600 ================================================================================ From: Mike Shaver (shaver^off.net) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Fri, 31 Jan 2003 13:55:17 -0500 On Jan 31, Paul Bleisch wrote: > There is no silver bullet. Validation of data takes non-trivial > effort. The best you can hope for is a system whereby you can > add validation rules easily and quickly. That way you can build > up validation rules over the life of the project. Yes, I very much agree. I guess I was fishing for the techniques and design choices that people have found make that "incremental validation" easier or harder. What do you have to trade off? (Other than time, I guess, but have people found a way to inexpensively generate validation rules from some other data set, like script analysis or crystal balls or a ThatcherBot?) Mike ================================================================================ From: "Peter Lipson" (peter^toysforbob.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixed pool allocation Date: Fri, 31 Jan 2003 11:05:16 -0800 funny example you chose- the last PC game I worked on, that's exactly what happened. "Doors" were animatable and triggerable elements in a scene so the designers used them any time they wanted some part of the world to move in response to some player action. If they wanted the rifle barrel to move when the player fired, they'd probably have tried to use a door for it. The problem comes when the designers make poor choices about which game element to use. They have a tendency to use the component they're most comfortable with and beat it into place with a hammer. Allowing them too much access via too flexible a data-driven object system would result in a chaotic system of objects. (I'm sure some designers can follow good programming practices, but I haven't worked with many who can...) Peter ================================================================================ From: Ray (ray^guildsoftware.com) Subject: Re: [Algorithms] Game Entities - avoiding inheritance / fixed poo l allocation Date: Fri, 31 Jan 2003 13:10:44 -0600 I really like your idea, Wayne. It would work well for simple objects. Thinking about our stuff, we have an object that can explode, but a derived class has health that calls the Explode function on the base class. I think some of our stuff is ugly, but it works, and I find these threads about game entities really interesting. - Ray > Right, I think this is what I meant by attributes. You have a 'definition > schema' like: > > Component Damage > Float attribute Health > EndComponent > > Object Door > uses damage > { > health = 50; > } > > uses explode > { > } > EndObject > > So the damage component allows the designer to modify the health (or > 'starting health'). The damage component maintains it and fires off the > 'destroy' message which is received by the explode component. This isn't > very well defined, 'cause I haven't thought it all the way through yet. I > think I'm missing something :) > > This doesn't really show why you'd want to expose the 'health' attribute > either, what if it was a 'Man' object, and there was a 'movement' component > it might want to alter the movement as the health decreases also? > > Wayney ================================================================================ From: Chris Hecker (checker^d6.com) Subject: RE: [Algorithms] Game Entities - avoiding inheritance / fixedpool allocation [bcc][fake adr] Date: Fri, 31 Jan 2003 11:32:42 -0800 Gil: >I agree with what Charles is saying below. To me, emergent behavior >emergent bug. And it also becomes hard to predict the consequences of >minor code changes. >I don't really see the market clamoring for emergent behavior in general. Christer: >Please don't link emergent behavior with data-drivenness. They are two >completely different things. You can _obviously_ have emergent behavior >with code that is completely hardwired. I think a bunch of things are getting conflated here in this thread: 1. Emergent behavior vs. emergent gameplay. I think that, like "data-driven", "emergent behavior" has some kind of religious connotation to it these days, which makes it a hot button for both pro-hype and anti-hype people. Your gam