March 02, 2005

Sideways data

We're taking an interesting approach to data in our new prototype. In every project I've worked on in the past 6 years there was always a class like this


class GameObject
{
    Vector3 Position;
    char* Name;
    Geometry *Renderable;
    //etc etc etc
    virtual int Use();
};

Which leads to classes like this:


class PickupObject : public GameObject
{
    float PickupRadius;
    virtual int Use() { /* special pickup code */ }
};

And this is a perfectly valid approach that's worked well for thousands of games. It also seems to be a very natural way of thinking about the way to structure your data.

The main difficult with this approach is that it's difficult to keep your objects both lightweight and easy to refactor.

The approach we're taking:

Build a very simple lightweight database. Take all your data, divide it up into logical units (hitpoints, position, model name, physics data, etc) then each object gets an integer identifier. If an object needs a position an entry is added to the position database with the object's GUID. Property inheritance is done through a parentage/archetype database.

Restructuring data becomes a data problem. Use of data goes through a common query type interface.

There are known performance issues if you're looking for data that isn't there. This should be solvable with a combination of caching and strict rules governing archetype construction.

It's a bit like turning all the data on its side, but it seems to cause a few difficult problems (massive refactoring, inflexibility, data bloat, etc) to become a number of simpler problems (simple database design, simple reference counting).

--

Note: Other games (especially the Thief series) used this approach before we ever thought of it. Our work has been significantly helped along by presentations by: Doug Church, Michael Doherty, Alex Duran, and others.

Posted by matt at 10:55 AM | Comments (0)