</teesside><virtual-playground>

Well, my University life is over, I’m no longer a student, and I’m staggering, blinking, into the light, arms open and ready to embrace the Real World. In fact, the transition hasn’t been so difficult. I started work back at Virtual Playground – the company where I completed my industrial placement – almost immediately upon completing my course. Nothing had really changed in the year I’d been gone, so I was able to hit the ground running, already familiar with the codebase and the toolchain used there. We completed Prison Tycoon 3, and then moved on to do some refactoring concurrently with our next project.

Probably the biggest part of this refactoring effort has been the move to an aggregation-driven object system. That is, up until now we’ve had a classic deep hierarchy, adding functionality by deriving new classes, pushing functionality further up the hierarchy when we need to share it, and so forth. This is not ideal. We’ve been told time and again how composition is more effective, more flexible, and generally safer than inheritance. Many of us are already comfortable with the inheritance-driven model, though, and are used to working with it and finding ways round its flaws.

Since reading Mick West’s March 2006 article in gamedeveloper magazine, “Evolve Your Hierarchy”, I’ve wanted to try out composite object systems, and see how much extra flexibility they give you, and whether usability suffers as a result. I was finally given the opportunity a month ago, when I was asked to take our existing inheritance-driven hierarchy (from basic objects that can load and save down to AI-driven characters that can make decisions, have FSMs, pathfinding, and spline-following capabilities), and start writing aggregate equivalents. Since the current title is quite simple I’ve only had to replicate a limited subset of the functionality that existed in our original system, giving me more time to focus on the design issues involved.

We’ve gone for what West calls a “Component Container” in his article, whereby we still have the idea of a game Entity as a concrete object, to which we can attach Behaviours. These Behaviours consist of small, very specific classes adding a particular function to the Entity. We’ve tried to be quite strict about limiting the scope of their abilities – if a Behaviour gets too hefty we split it up into two separate Behaviours. So far it’s been very successful. We’ve been able to replicate all the functionality we’ve needed so far from the old system, and we quickly got used to the idea of creating a new Behaviour and attaching it, rather than creating a new class and deriving it. We’ve taken the old object factory, which allowed artists to specify how the objects they were adding to the game should act, and added the notion of Behaviours – so objects of each type have a set of default Behaviours, after which more can be attached to extend functionality for that item in particular.

The main difficulty we’ve come across is communication between these Behaviours. In an ideal world, the Behaviours would be entirely self-standing, and we could simply depend upon their standard clone()/init()/update() interface to run themselves. Tragically, the world is not ideal: the Animation Behaviour will need access to the mesh in order to animate it, but the mesh is stored within the SceneNode Behaviour. The FSM Behaviour (when we write it) will need to tell the PathFind Behaviour where to go, will need to pass the path found by PathFind to the SplineFollow Behaviour, will need to tell the Animation Behaviour to start the walk animation, and will need to update the position of the SceneNode. There is a lot of intercommunication. So far, we’ve been fairly flexible about giving access to Behaviours – they can be retrieved from the Entity storing them, and since each Behaviour has a handle to its parent Entity they can be accessed from within or without.

All in all, I’d highly recommend this style of object composition. It’s easy to use, and quite intuitive for those of us coming from an inheritance-oriented background. After a while, you realise that the Entities are not really necessary; a component manager could be used to store a variety of Behaviours which have an entity ID to describe how they fit together, in what West calls “Pure Aggregation” in his article. The Entities in our system essentially act as localised component managers. West recommends this as an intermediate solution, and to a degree I agree – the purely aggregate system has an abstract and simple beauty to it, and is incredibly flexible and powerful. However, the idea of concrete Entities can be a useful one, and I think so long as we are limiting this system to in-game objects (as opposed to all game functionality, including scripts and triggers, etc.) we will probably keep them.

Leave a Reply

You must be logged in to post a comment.

  • Recent Tweets

  •  

    September 2007
    M T W T F S S
    « Aug   Oct »
     12
    3456789
    10111213141516
    17181920212223
    24252627282930