Life of an XNA Game
One of the trickier parts of starting out with XNA is figuring out what is called when and by whom and where you can put this or that without breaking something. It’s somewhat confusing at first. So I’m going to try to explain the flow of an XNA game as best I can. I can’t use Visio to save my life (at least not to create something coherent), so you’ll have to live with a text description. Let’s just dive in:
First your game’s constructor is called. No magic happens here and technically speaking you don’t have to have any code in your game’s constructor. You could move all the template code to Initialize (as long as it’s before you call base.Initialize()) and everything would work just the same.
Next the Run() method is called on the game. This is what starts all the hidden stuff that nobody knows. There’s a lot going on behind the scenes, but for now we’ll just talk about the common stuff:
- First you’ll get a call to Initialize. This is where you generally put non-graphical initialization code for your game*. You also need to make sure you call base.Initialize(). When you do, the game does a few things:
- Calls Initialize on each GameComponent in the Components collection.
- Creates the GraphicsDevice.
- Calls LoadContent on the game.
- Calls LoadContent for each DrawableGameComponent in the Components collection.
So if you’ve ever gotten that “GamerServicesComponent is not Initialized method” and your method call was before base.Initialize(), that’s why. It’s also worth noting that it is base.Initialize() which will call LoadContent for your components; not base.LoadContent(). The base Game implementation of the LoadContent method is empty. This means you can simply not call it and nothing will change.
Another note is that adding game components in Initialize but after base.Initialize() will result in them not being initialized by the game. There are three ways to deal with this:
- Add the component before base.Initialize().
- Manually call the Initialize method of the component.
- Override the BeginRun method and add the component there.
- Next we enter the main game loop of Update/Draw. At this point, any game component added to the Components collection will be automatically have Initialize and, if the component is a DrawableGameComponent, LoadContent called. The game remains here until the told to Exit.
- Now your game is exiting so UnloadContent is called on your Game. UnloadContent is also called automatically on your DrawableGameComponents so you do not need to call base.UnloadContent() at all (unless it makes you feel better; then go for it).
That’s a very high level look at it, but it should answer some questions. Those being these big points:
- If you are doing some initialization that relies on the GraphicsDevice, put it in LoadContent or in Initialize after you call base.Initialize().
- If you are doing some initialization that relies on a game component being initialized or loaded, put it in LoadContent or in Initialize after you call base.Initialize().
- If you add a game component in the Update method, it will automatically have the Initialize and, if appropriate, LoadContent methods called.
Hopefully this helps out more than it confuses. I’ll admit I’m not the best at explaining this flow, but since I’ve seen the question come up a couple times I figured I’d take a stab at it. If you want one of the best ways to find the flow, I’d recommend grabbing Reflector (free download) and opening up the XNA dll files. There you can trace the Run method and follow what the framework is doing line by line.
*: In my experience, I’ve found little use for the Initialize method. Personally I stick any initialization code that doesn’t rely on the graphics device or game components in my constructor. I’ve yet to find any real good reason why I should put that code in Initialize instead of the constructor. If you have a good reason, please leave me a comment. I’m always up for realizing something I hadn’t previously.
EDIT: Thanks to one of my colleagues at Visi3D I now have a diagram of the process. Send all your love and thanks to Gary for this:
The primary reason I’ve found for using the Initialize method is when the construction of one object relies on the construction of another. If we make two objects, A and B, and A gets constructed before B (for whatever reason), but A’s constructor relies on the construction of B, then we can move that reliant code into A’s Initialize method. Sounds a little weird, but there are several actual non-graphical examples of this in my current game project.
Constructors get less useful when you start doing inheretence. In C++ and Java, and I assume C#, a base class’s constructor has to be called at the beginning/before a subclasses constructor -for reasons to do with the way Objects memory is allocated. So using constructors for more than very basic initialisation can cause problems.
My memories a bit hazy about all this stuff though.
I use Initialize to reset game components. When a monster dies, I remove it from the game.components collection and if I need a new monster I just add it again and initialize is called automatically.
Couldn’t find a terribly good place to ask a question, but I’m working through your tile engine tutorials and have an issue. I’m on part 4a and we’ve just hit the index out of range exception after trying to merge the rock layer with our original layer. I added in the two lines of code stating that if we find a negative 1 to continue, but the exception still keeps popping up. Suggestions?
Nevermind… I found my mistake. I failed to change one line to layer2 in the game1.cs file. BTW, great tutorials