First, a quick introduction. My name is Andrew and I’m the resident programmer here at UBS. Every now and then I’ll post about my experiences programming games or any other interesting thing I happen to be working on.
Today I’m going to talk about game architecture. I don’t mean designing buildings to put in the next GTA, I mean architecture in the software engineering sense of the word. How your code is organized to make it easier to maintain and extend. Specifically I’m going to talk about how to manage the entities in the game world.
A warning: this article has turned out to be quite lengthy and you’re probably going to need some knowledge of software engineering to understand it properly. But if you don’t then you probably wouldn’t be too interested anyway, so it all works out in the end.
An entity is generally thought of as some sort of object in the game world. Entities are anything from the player character to a projectile or a piece of scenery. Usually even invisible things that have an effect on the game’s world such as an event trigger are entities. The traditional way of organising the code for these entities was to use inheritance and lots of it. If you’ve ever played around with the actor browser in UnrealEd you’ve seen that there is a massive nested list of actors (that’s the Unreal Engine word for entity) that can be placed into a level.
As the number of different entities increases this can become very unwieldy. Another approach is to use components. Rather than each type of entity inheriting it’s functionality and behaviour from it’s parent class, it just becomes a collection of components. A component defines a specific behaviour that its owning entity will have. That way you can mix and match components to create any type of entity you want. Say you want a redeemer style rocket launcher. Just add a controller component to your rocket entity and away you go.
I won’t go into too much detail about component systems in general because there’s already some great articles out there on the subject such as this one by Mick West. My implementation of a component system differs a little from what’s described in that article so I’ll focus the rest of this article on how mine is different and why.
Component systems sound really great in theory but they’re not without their pitfalls. Quite often components depend on functionality from other components which brings up the question of how components within an entity communicate with each other. One common solution to this problem is a message passing system. When a component needs something from another, it passes a message to it’s owning entity which then routes the message to the appropriate component. Then the same thing happens in reverse for it’s response. This sounds good because objects are kept loosely coupled. It doesn’t care what type of object it’s interfacing with, all it cares about is that it gets the right data back. However this message passing system requires you to design your own message structure and has some overhead when encoding and decoding the messages.
My solution is a bit different. Perhaps not so nice from an OOP perspective, but so far it seems more programmer friendly. An event is raised on each component when another component is added or removed from the entity. This allows components to inspect what type of component has just been added and can hold a reference to it if it’s needed. You have to be careful with this approach. It’s important to check you have a reference to a valid object before you try to use it, and you have to make sure to take note when it’s removed from the owning entity.
A real example of this is my GroundWalker component. This component ties together functionality to make a character that walks along the ground. It depends on a physics component to keep track of whether it’s actually on the ground or not, an animation component (to make sure the right animation is playing for the current walking state and a controller component to drive the character. Sometimes this can result in tight coupling of classes which is an OOP no-no. But in this case it doesn’t really make sense to have a walking character without knowledge of the physics engine so I think it’s reasonable that it depends on a specific implementation. In the case of the controller component, this is actually using a controller interface so it’s actually irrelevant whether it’s being controlled by a keyboard, gamepad, a network interface or even an AI.
Some common functions that are usually needed on a per-frame basis are called on every component. This includes a generic update method, a collision event and 2D and 3D rendering. Not all components need these things but I decided they are common enough to be included in the component interface.
Another implementation issue is that knowing the position and perhaps the orientation of an entity is important to a lot of components. This could be solved by each component keeping it’s own reference to say a physics component that provides this information. However these things are so often needed that I decided to make a more convenient solution. Components that implement a Physics Model interface are treated as a special case for the entity. It holds a specific reference to this type of component so that it can pass on position information to any other object that needs it.
After a weekend of refactoring the codebase I feel it’s now much nicer to work with. And I don’t feel like my time has been wasted despite the fact the engine doesn’t actually do anything it didn’t do before. I hope that from now on it’s going to make it much easier to add new stuff as the project progresses.