What are XNA Game Components?
Recently, while working with XNA I came across a few classes I hadn’t noticed before. It turns out that interfaces I often write myself, IUpdateable and IDrawable, already exist. When I found them I wanted to know more. They rarely appear in the MSDN code samples I’ve seen, and searching online, it appears most people are as perplexed as I am about what to do with them. So after playing around with these interfaces and their sibling the GameComponent here are some thoughts on what they are and how they fit into a larger project.
The starting point for a game in XNA is the Game class. It so happens that this class has a collection of GameComponents which manages updating and drawing each GameComponent. Because of this making your game objects GameComponents seems like a good way to hook directly into the XNA game loop.
In fact, it almost feels like adding DisplayObjects to the stage in Flash as GameComponents have a lifecycle which the Game will follow. What this means in practice is that as long as you’re dealing with GameComponents it’s really easy to add things to the game. Want to add a tween? Just create one and add it to the list of GameComponents. No need to hold a reference or manage its life cycle.
In my book those are some pretty compelling features. So what’s not to like? In my opinion there are three main problems with the GameComponent class which make me recommend against adopting it throughout your code.
1. Inheriting from the GameComponent class requires taking a dependency on the Game object
In practice, your game objects will likely need some means to communicate to the game in order to add or remove other game objects, and it would be fair to solve this problem by holding a direct reference to the Game object. However, by using GameComponents you are forced into this decision. This means no event mode or interfaces — no indirection between your game objects and the game.
2. GameComponents need services; Services lead to questionable design choices
GameComponents will often query the Game’s list of registered services in order to function. Due to their fancy name, services sounds rather innocuous. In truth, a service is really nothing more than a global object with a thin layer of indirection wrapped around it. So while I believe it’s possible to write against services without tightly coupling your code to, say, the SpriteBatch. In practice I’ve found services let me be lazy at the expense of good design.
3. Your classes will be hard or impossible to unit test
It follows from the above that in order to instantiate one of your game objects you will need an instance of the Game class. Unfortunately, the game class is sealed meaning that you cannot subclass it or swap out its implementation. In my opinion, if you have to create an instance of the Game class in order to test your game object’s AI then you’ve failed at unit testing. In effect you’re having to fly the plane to test its coffee maker!
So I wouldn’t recommend writing against the GameComponent class, but what about the IUpdateable and IDrawable interfaces I mentioned above? As it turns out both those interfaces are free from references of the Game class. So if they make sense for your project I’d go for it. However in practice, I’ve found that I don’t really need all of the behavior defined in these interfaces. While I feel like the XNA needs something akin to the Stage in Flash I’m not ready to make a deal with the devil quite yet.