Using RTTI in an entity component system?

Started by
8 comments, last by Antheus 12 years ago
I've looked for information on RTTI but all I've found is "its bad avoid it!" or "why would you even consider it?"
What I want to know is its pros, cons, uses and alternatives.

As stated in the title I'm considering it for an entity component system for a flexible game dev kit.

Any and all help appreciated,
Thanks in advanced,
Bombshell
Advertisement
RTTI is basically intended to do stuff like you would typically do in a component system.

The usual reason people suggest avoiding it is either (A) it can encourage bad design habits (which is true, but in this case irrelevant) and/or (B) on some compilers it doesn't perform very well.

Usually most people doing serious component systems in C++ implement their own replacement for RTTI. I'm sure there's some good articles on this floating around the web; I think AltDevBlogADay had one a while back.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

A great entity system today would be JavaScript.

Prototype-based, ad-hoc composition, possible to include OO concepts if needed.

If making an entity system in C++ for sake of flexibility and it is going run-time dynamically typed (aka RTTI), then you need to implement exactly the same thing as JavaScript VM. Might as well reuse what's out there. There's also bunch of problems with allocations and general life cycle of either components or entities and type system mismatch.

If making it for performance reasons, then run-time typing is poor fit both performance-wise as well as being a poor fit for GPUs. But it's more about programming model itself than entity systems as such.
thanks,
what I'm getting from this is if possible make your own system to save space.
But is there a computational overhead from using the C++ built in or is it essentially what's explained here:
http://www.altdevblo...type-id-is-fun/

I don't mind a little memory overhead (as long as in a general gaming environment it won't cause manic resource munching.
Slightly related, what would be a good practice for making sure all objects derived from entity get an ID at both Compile and runtime? I intend to use such ID's (as well as a parameter list defined per interface and object) in a level layout allowing simple storing for level editors.
An automated system would be beneficial as I intend users of the engine to include their own actors in libraries, so if automated its 1 less thing to ask of the users (who for a time will be myself and my team, so going non-automated would be okay as a short-term solution)

EDIT: just noticed antheus's post.
I'm not getting the conclusion of your post, if aiming for simple flexibility RTTI but if aiming for performance flexibility work your way around it? thats what I'm getting but I'm more than likely wrong, would you care to elaborate?
Entity systems emerged to counter rigidness of inheritance based designs.

Instead of having rigid interfaces, types become emergent - something that has velocity is updated by physics system.

Such approach brings about many issues, from memory management and structure layouts, to deciding what exactly a certain "thing" can do. All of these problems are mostly solved by dynamic languages.

Designs like this can be compared to relational databases. SELECT velocity, mass FROM ... - give me everything with velocity and mass (so I may multiply them) regardless of where it comes from. The latter example avoids need for dynamic typing - those are either resolved at selection time or through an implicit conversion.

C++ is painfully static language with minimal run-time polymorphism support making it a very poor choice for such systems.

defined per interface and object[/quote]
Approach like that is quite counter-productive. It throws away the built-in OO facilities and doesn't provide the flexibility of composition.

I mentioned JavaScript above:var Enemy = function() {
this.velocity = [1.0, 2.0, 3.0];
this.mass = 200.0;

systems.install(this);
}
Above defines an object. No includes, nothing else. We simply make up stuff and say "this is what we use to represent an enemy".

Magic comes from 'systems.install'. That method takes an object and examines its properties. For our case it sees that it has "velocity" and "mass", so it puts it into Physics system list. So each time physics is updated, so is our enemy. Physics system them works like it normally would - it reads velocity and mass of each entity, performs the calculation and moves on.

Defining new objects, extending existing ones or otherwise iterating requires no rigid interfaces and relies mostly on convention. Helpers can obviously be written for various parts.

But unlike typical system in C++, which would require thousands of lines of code before first Entity could be defined, the above is really all there is. There lies the great flexibility of composition/entity approach. At same time, designs like that aren't suitable for certain computationally intensive tasks and example like above would mostly likely not scale well for actual physics computation - though it's perfectly fine for small to medium scale.

For performance, the design would be different from ground up:List<Position> positions;
List<float> mass;
// one list for each property
struct Entity {
vector<int> members; // members contains index of respective property (5 in positions) or -1 if object doesn't have a certain property.
};

While too trivial for real world, one operates on List<>s and entities are merely used for tracking of membership. Such designs are considerably harder to iterate. They're hardware, not developer friendly.

I mentioned JavaScript above:var Enemy = function() {
this.velocity = [1.0, 2.0, 3.0];
this.mass = 200.0;

systems.install(this);
}


With some template magic and type erasure this can actually be emulated in c++, for example, I use this:

prototype p = system_manager.new_prototype();
p.add_component( velocitity{ x , y , z } );
p.add_component( mass{ 200 } );
entity a = system_manager.new_entity( p );
entity b = system_manager.new_entity( p );

which doesn't look that much worse. The idea is to have references to base_system s in your system_manager. During its initialization, you create a map< typeinfo , unsigned int >, where the value type is unsigned int. When adding a component to a prototype (usually while loading a level) you lookup that system_index in the map once and store it with the component. To create an entity from a prototype you simply iterate over all components in it and do

systems[ system_id ].insert( component );


Maybe I'll refactor my implementation a bit and upload it somewhere, it is, as you said, quite some work to implement a generic component system in c++.
which doesn't look that much worse.[/quote]

Of course not.

But you need to implement everything, including memory management, template magic, component containers, introspection, components ... Next you need to make a build, download, build and install the libraries, etc...

Further, you need to implement Velocity type, mass type (even if a simple struct it's 5 lines of code) and write all the extra facilities (serialization, type conversions, initialization) for each of them.

And after you've done all of that, wrote thousands of lines of code, spent hours administering the project and dealing with bugs, all you will have to show for it will be definition of a component which contains a vector and a float.

Dynamic languages give you this out of box.

They aren't solution to everything and come with a possibly unacceptable penalty for projects above certain size. But if trying to experiment with design they are definitely worth looking into it.

Maybe I'll refactor my implementation a bit and upload it somewhere[/quote]
Beauty of existing VMs is you already have that. No need to have someone write it, debug it, test it, build it, install it, tweak it, tune it, .... Make an empty file, write 20 lines of code, 18 of which will be the design itself.

a flexible game dev kit.[/quote]

If flexibility is a priority, then it's been done. Instead of reinventing the plumbing, just provide a few helper classes for drawing to canvas or webgl.
Alternatively, use Lua, provide a bridge to SDL or similar.

Writing yet another component container , especially a flexible one, is not the most productive direction.
By the sounds of it it'd be better I find an already working system and build around it or inspired by it?
Do you know any libraries, frameworks, etc. that could be of use in an Entity component system?
I'm not exactly planning on building the entire engine from scratch, my main interest being graphics programming I'd think myself better off building that as my speciality (I've seen a lot that "jack of all trades" doesn't sit well in Game development and that people prefer to hire someone for their speciality.)
That's not saying I'm not willing to learn it and of course I'd not mind learning the theory and etc. but if implementing an efficient model is as big as you say I'm assuming it is in itself a speciality.
I would recommend creating your own RTTI class. 3D Game Engine Architecture has a simple example of creating your own RTTI class that works without much overhead. Whether you want to use your own engine or something already made is really up to you. If you want to completely understand graphics programming I would recommend just making a rendering engine. If you do that you wont have to worry about collision detection, or physics and can work soley on graphics rendering.

Brendon Glanzer


Do you know any libraries, frameworks, etc. that could be of use in an Entity component system?


Here's the interesting part - they aren't needed anymore (with certain reservations).

Once upon a time, there was C and C++. Rigid, statically compiled type system. With long build times, things were too slow development-wise. Changing a single variable often mean recompiling everything and changing tons of dependencies. Runaway OO caused rigid hierarchies which didn't evolve well, unless developers happened to have lucked out.

Lacking viable alternatives, developers worked around these limitations by inventing stuff like entity models and whatnot.

During recent years, hardware changed, languages and runtimes matured and a whole new level emerged.

Component/container frameworks are essentially dynamic prototype-based languages. At core, the "object" is nothing but a bag of named key/value pairs. Values are rich (know how to converted themselves between types), making entire system introspectable, serializable, modifiable, offer REPL and more.

What once required tens of thousands of lines of scaffolding is now available in a reasonably performant language. All these details about entities and how to implement dynamic_cast and whether RTTI is too slow etc... These were all just limited replications of what dynamic languages are.

Once upon a time, function calls were a big evil thing. Slow, bulky, inefficient. Then polymorphism. And so on.


Goal of "entity" system is flexibility and quick iteration. Precisely what dynamically typed languages are.

my main interest being graphics programming I'd think myself better off building that as my speciality[/quote]

Then you should focus on studying linear algebra and shaders. Graphics are math, which then gets encoded in some way, whatever the hardware requires.

but if implementing an efficient model is as big as you say I'm assuming it is in itself a speciality.[/quote]

I said the opposite. Most of the type efficiency simply doesn't matter. For all but a few dedicated specialists, the problems of efficiency simply won't come up.


But really, in 2012, optimizing RTTI simply isn't relevant anymore. And if you ever find yourself in dire need of such optimizations, then there's 15 year old books which solved the problem.

Knowing C++ and detailed quirks might still matter, a lot of coding might still involve it, but in general, the fungible parts (the ones which require run-time typing) are simply done as scripts. What will remain as native code are the critical API codepaths.

This topic is closed to new replies.

Advertisement