Research into C++ Object / Attribute System for Low-Level Game Frameworks

Alex J. Champandard on November 5, 2008

Most commercial games have their own object / attribute system. From one engine to another, these frameworks provides more or less features depending on the style of C++ that’s used. In general, the job of an object / attribute system is to provide a variety of features which help building the rest of the game code on top.

For instance, there are a bunch of common game development tasks that you can use an object / attribute system for automating the process of:

  • Binding an object to a scripting language or console commands.

  • Serializing an object to disk in binary form and restoring it.

  • Packing up attributes of an object to send over a network.

  • Providing runtime introspection facilities to the game code.

There’s a variety of articles on this topic, and here’s my research on the subject. Big thanks go to Nick Porcino for both providing source to his experiments and blogging about his reading. Also, credits go to Bjoern Knafla and Javier ArĂ©valo for providing useful pointers in the forums. Read this thread in our forums for more details (free registration and introduction required).

This posts looks at the background research behind such object systems. Stay tuned for a follow-up article on the subject as these ideas are applied to the Sandbox!

How Does It Work?

The basic idea is to use a subset of C/C++ to help expose variables. This is almost like a domain specific language for the kind of attributes you need to expose, and what information each attribute needs to have (e.g. name, type, description, version, accessor / mutator, etc.).

For example, the code could look like this for a simple object that needs to have meta-data about attributes:

struct MyObject
    BIND(MyObject, a, int, "Space for A.");
    BIND(MyObject, b, float, "Variable of B.");
    BIND(MyObject, c, double, "Contains C.");
    BIND(MyObject, d, std::string, "Stores D.");

  int a;
  float b;
  double c;
  std::string d;

There are a few online articles you can read on the subject, to get more information about different implementations:

It’s useful to realize that you can start with a pretty simple system, and as long as it can be easily introspected, new features can be added on top without too much work. The basic information required is an array of attributes that’s stored per-class and accessible per-instance, such that data can be retrieved from objects at runtime after they have been initialized.

struct Attribute
  Type type;  // Enumeration of possible types.
  void* pointer;  // Member variable pointer.
  const char* name; // String for debugging.

class Object
  static std::vector attributes;

That’s the gist of it in theory; it’s not complex since it’s the kind of stuff other more dynamic languages provide by default, but in practice when you implement it at a low-level in C++, there are many choices to make.

Implementation Choices

Many of the decisions of how you build the system will depend on your programming style. These may not affect the end-result, but such decisions often have an impact on efficiency and usability. For instance:

  1. How extensively to use C++ templates vs. macros and function pointers.

  2. Whether to require inheriting from a base class to provide core functionality.

  3. If you should support versioning of the attributes or not, and how to fallback.

  4. Whether variables can be bound under different names if necessary.

  5. How to expose the code, in a class header or hidden in the .cpp file.

  6. If the overhead for attributes should per instance or once per class.

  7. Whether to reimplement C++ language features more simply and efficiently.

  8. How to reduce declarations and redundancy when the attributes are declared.

  9. If you should rely on external tools or parsers to help create the definition.

Nick Porcino has a lot to say on this subject, in particular he asks Why Roll Your Own RTTI?, he ponders about a A Simple Type Mechanism and finally he considers using an efficient StringMap for attribute lookups.

If you decide to go for the meta-programming approach outside of C++, there are some other systems you might want to look into. In particular, check out Naughty Dog’s
Adventures in Data Compilation (PDF). Trolltech also uses an external tool to pick up some of the event tables and other declarations inside the code; for details see Meta-Object System in Qt. Finally, you might want to check out the Reflex project which provides this kind of functionality for C++ code.

Other References

Dynamic Type Information
Scott Wakelin
Game Programming Gems 2, 38-45.
 A Property Class for Generic C++ Member Access
Charles Capelli
Game Programming Gems 2, 46-50.
A Generic Tweaker
Kasse Staff Jensen
Game Programming Gems 2, 118-126.

If you have any comments, references or additions feel free to post them in the comments below!

Discussion 3 Comments

Ian Morrison on November 6th, 2008

Posted this at just the right time, Alex. I'm right in the middle of rebuilding the engine for my game, and that includes rewriting the object management code! I'm already looking at taking advantage of some of the attribute management code you've linked to. While you're on the subject, how do you think the object system should be designed to be AI friendly from the ground up?

alexjc on November 6th, 2008

For AI, the biggest things I would think about is reducing the cost of flexibility. Ideally, you'll want lots of dynamic attributes / properties to remember dynamic facts, provide custom behaviors per-instance, etc. So I'd focus on: [LIST] [*]Making access of dynamic attributes efficient, without string lookups. [*]Easy ways to identify frequent dynamic attributes and make them static. [*]Reduce memory allocations similarly, use statics for the common cases. [/LIST] A secondary thing I'd focus on is complex relations between objects, so you can model knowledge about things and meta-knowledge. "I know that you know XYZ." But that's more of a research topic than development. Alex P.S. See this [URL=""]awesome post[/URL] by dmail for more references.

DDd on November 6th, 2008

This is one of those areas, that should result in a definitive answer, there should be a well balanced object model that is efficient for 90% of the use cases. I am definitely going to follow up on your links and research, thanks for putting it all together.

If you'd like to add a comment or question on this page, simply log-in to the site. You can create an account from the sign-up page if necessary... It takes less than a minute!