Catching Exceptions on Xbox 360
A common issue when working on an Xbox 360 game is that inevitable time when you package up a CCGAME and send it to a buddy, only to have it crash and burn. Generally at this point you’ll feel a series of emotions including one or more of the following:
- Annoyance
- Anger
- Frustration
- Blind Hatred
The problem in this case is that, while you have Visual Studio to help you catch exceptions, people running your CCGAME do not. This means friends who are helping you test or peer reviewers are going to be unable to help you debug these issues unless you can reproduce them on your own.
Luckily there actually is a way for you to trap and display unhandled exceptions. This means people playing your game will be able to give you much better feedback on why your game crashed.
Implementing such a system is really quite easy. First you create a second Game type in your game project. This game takes in an Exception as a parameter and then simply displays it to the screen, waiting for Back to exit:
public class CrashDebugGame : Game
{
private SpriteBatch spriteBatch;
private SpriteFont font;
private readonly Exception exception;
public CrashDebugGame(Exception exception)
{
this.exception = exception;
new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void LoadContent()
{
font = Content.Load<SpriteFont>("MyFont");
spriteBatch = new SpriteBatch(GraphicsDevice);
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
Exit();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
spriteBatch.DrawString(
font,
"**** CRASH LOG ****",
new Vector2(100f, 100f),
Color.White);
spriteBatch.DrawString(
font,
"Press Back to Exit",
new Vector2(100f, 120f),
Color.White);
spriteBatch.DrawString(
font,
string.Format("Exception: {0}", exception.Message),
new Vector2(100f, 140f),
Color.White);
spriteBatch.DrawString(
font, string.Format("Stack Trace:\n{0}", exception.StackTrace),
new Vector2(100f, 160f),
Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
Then simply modify your Main method (generally found in Program.cs unless you have moved it) to use a try/catch block, running the debug game when it catches an exception:
static void Main(string[] args)
{
try
{
using (PrimaryGame game = new PrimaryGame())
game.Run();
}
catch (Exception e)
{
using (CrashDebugGame game = new CrashDebugGame(e))
game.Run();
}
}
Finally we can test the system by changing our primary game’s Update method to throw an exception when you press Back instead of exiting:
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
throw new Exception("We broke the game!!");
And that’s it. Run the project on your Xbox 360 and you’ll see your game will switch into debug mode whenever an exception is thrown. I’ve also prepared a downloadable version of my test project which you can snag here: XboxCrashLogDemo.zip. Hopefully this helps everyone in making the best Community Games that they can.
Possibly Related Posts
(Automatically Generated)How Not To Write A Game – The Reports of the Xbox 360 GC Are Greatly Exaggerated
A More Robust Exception System
Using GamerServicesDispatcher to fix up exception handling
Dynamically Refreshed Assets in XNA
Write a Tutorial, Win an Xbox 360!