Components and Services

The XNA Game class is a solid foundation to build your game on. To help you organize
your game code into manageable modules, XNA also provides a small service framework that you can
use to build reusable components that provide services to the rest of the game.

This framework comes in the form of the GameComponents collection in the game
class and its GameServices registry. If you don’t know how all this works yet,
don’t worry, that’s what this article is about!

Exploring GameComponents

Games typically consist of several logical modules that could ideally be reused between
different games. For example, a lot of 3D games internally employ a scene graph to manage
the visual entities in a game (models, decals and so on). This scene graph could be written in
a general manner so that two very different games could use the same scene graph module.

This is exactly what the GameComponent class is about. Instead of spreading your
graphics, scene graph and text rendering code all over the place, you can cleanly seperate
these parts of your games into components that you can then give to other XNA developers or
reuse in your next project. Here’s an example of which GameComponents you might
decide to create for a simple application:

GameServices

But now the TextRenderingComponent needs to access the
GraphicsComponent. And the SceneGraphComponent needs access to
the GraphicsComponent and the EffectManagerComponent. Was all
the separation in vain? Will all these components need to know of each other and develop
a tightly woven net of interactions that makes it impossible to take one of them and put it
in another project?

Not quite. That’s where the GameServices collection comes into play. Basically,
a game service is just an interface under which you access a component. The built-in
GraphicsComponent, for example, has the built-in IGraphicsDeviceService
service which allows access to the GraphicsDevice that is managed by the component.

It works like this:

First, all GameComponent-derived classes that you added to your game are created
and put into the GameComponents collection.

Each time a component is added to the collection, its OnGameChanging() method is
called. Here the component will register its services to the GameServices
collection.

After all components have been added, the second stage initialization calls the
Start() method of all components. Here components can pick the services of other
components they require.

In the end, your game will not rely on the one and only GraphicsComponent being
there, but on some component that provides your game with the
IGraphicsDeviceService. And that could be a different component from game to game.

Your code might even choose to just skip graphics altogether if there’s no
IGraphicsDeviceService, but keep running neverthelesss (in a dedicated server,
for example).

GameComponent Interaction

Components that need to access each other do so only through well-defined interfaces that could
be provided by a different component in another game, or not at all. See this illustration
to get a grasp of the concept:

Take note of the red line. This is how the SceneGraphComponent accesses the
GraphicsDevice. It does not rely on the GraphicsDevice being provided
by the GraphicsComponent class, it only expects that the
IGraphicsDeviceService exists in your game.

When to Create GameComponents

Well, that’s really up to you. As a rule of thumb, any time you’re writing something you’re
likely to be needing in your next game, too, create a GameComponent from it.
Even if you need to modify it for your next game, it will give you a head start and
promote clean separation of responsibilities in your code.

There are two ways you can create your own game components:

You can create a game component by deriving a new class from either the
GameComponent or the DrawableGameComponent classes. These, however,
require a reference to the Game instance in their constructor. Which means that
you can’t use them unmodified if you ever plan to use WinForms together with XNA (for example,
to create a level editor).

The other option is to just implement the IUpdateable and optionally the
IDrawable interfaces in your class. You can then decide yourself if you want
to depend on the Game class, only the GameServiceContainer to register
your services or nothing at all!

Of course it's annoying to be implementing those two interfaces over and over again. That's why
I wrote myself these two base classes which behave exactly like XNA's GameComponent
and DrawableGameComponent classes, but don't require the Game instance
to be constructed. See my blog post titled To GameComponent or not to GameComponent
for more info and a download of those classes.

Example Code

Need some code? Here is the source code for an example component, a
SceneGraphComponent that publishes a service named ISceneGraphService
that can be queried for by the game class or by other components. If also shows how to use the
IGraphicsDeviceService interface to access the game's GraphicsDevice.

/// <summary>Interface for the scene graph service</summary>publicinterface ISceneGraphService {/// <summary>The root node of the scene tree</summary>
SceneNode Root {get;}/// <summary>Matrix used to transform 3D to screen coordinates</summary>
Matrix Projection {get;set;}/// <summary>Matrix that defines the viewer's location in the scene</summary>
Matrix View {get;set;}}/// <summary>Component to manage visuals using a scene graph&l;/summary>/// <remarks>/// <para>/// A scene graph basically organizes 'nodes' in a tree, where each node's position/// is local to the parent nodes position. If you would model a solar system, the/// planets would be children to the sun, while the moons would be children to their/// respective planets. Each moon would then only have to remember its position/// relative to the planet, and wherever the planet goes, the moon will be, too./// It is the same for the rotation of the parent node. The orientation of all/// child nodes is relative to the orientation of the parent nodes./// </para>/// <para>/// Scene nodes are not required to actually draw anything, you can create them/// just for the sake of categorization or in order to chain multiple independent/// transformation matrices without concatenating the intermediate steps. If a/// scene node wants to draw something, it can get hold of the GraphicsDevice/// by navigating back to the game instance through its 'SceneGraph' property./// </para>/// </remarks>publicclass SceneGraphComponent :
Microsoft.Xna.Framework.DrawableGameComponent, ISceneGraphService {/// <summary>Initializes the scene graph</summary>/// <param name="game">Game instance this scene graph belongs to</param>public SceneGraphComponent(Game game):base(game){
game.Services.Add(typeof(ISceneGraphService), this);}/// <summary>Called when all game services have been registered</summary>publicoverridevoid Initialize(){// Query for the graphics device service through which the graphics device// can be accessed
IGraphicsDeviceService graphicsDeviceService =(IGraphicsDeviceService)Game.GameServices.GetService(typeof(IGraphicsDeviceService));#if false // Example of what you could do here// Register to the graphics device manager's events in order to get notified when// our ResourceManagement.Manual resources need to be destroyed or recreated.
graphicsDeviceService.DeviceCreated+=new EventHandler(graphicsDeviceCreated);
graphicsDeviceService.DeviceDisposing+=new EventHandler(graphicsDeviceDisposing);
graphicsDeviceService.DeviceResetting+=new EventHandler(graphicsDeviceResetting);
graphicsDeviceService.DeviceReset+=new EventHandler(graphicsDeviceReset);#endif}}

6 Responses to “Components and Services”

Of course it’s annoying to be implementing those two interfaces over and over again. That’s why I wrote myself these two base classes which behave exactly like XNA’s GameComponent and DrawableGameComponent classes, but don’t require the Game instance to be constructed. See this article for more info.

Thanks for updating that, an interesting read and of great help!
Only just discovered your site and I have to say, not only am I impressed with the content but also the quick response to a mistake in the link! Great work!

Everything makes sense, but it raises another concern – how well does this approach play with Dependency Injection? Is there a way to make it known to the DI what dependencies does a component have, and what dependencies can it satisfy? Take Ninject for an example – the only dependency injection it supports is constructor parameter injection (which is great, as it enforces the dependencies to be explicit).

I think the entire game services concept exists in parallel to a full-blown IoC container – if you use Ninject, you won’t use game services. And good riddance, too, since the way XNA envisioned its services is pretty much the Service Locator antipattern 🙂

Game components (or, to be accurate, IGameComponent, IUpdateable and IDrawable) are still useful, even under Ninject, as adding them to the Game.Components collection lets them take part in the Update() and Draw cycles.

For my own XNA projects, I’ve got NInject to completely take over the Game class (providing services such as IGame, IContentManager and ISpriteBatch) and my actual game code resides in GameComponents that use constructor injection to get their services. For backwards compatibility, I also bound the concrete Game, SpriteBatch and GameComponentCollection as services and my Open Source components both support constructor injection and adding themselves to the GameServiceContainer. Worked out pretty well in the end 🙂

I created a small example project using those bindings for an article I haven’t yet carried over from my old website. If you want to check it out: Nuclex.XnaNinject.Demo.7z.