7 min read

Managing Content in MonoGame

Introduction

In this tutorial, we’re going to cover how to load content into your game. Content management in MonoGame has historically been somewhat painful, requiring you to piggyback on XNA’s content pipeline. But recent MonoGame builds have fixed this, and it has now become (relatively) easy to work with content in a MonoGame project.

Content in MonoGame

Let’s start with a brief definition. Content is any sort of art asset that your game uses. In a few rare instances, content can even be code, perhaps in the form of shaders and scripts, etc. For the moment, we’ll be primarily focused on the art aspects of content, including fonts, images, 3D models, music, sound effects, and video.

Comtent Pipeline file in the Solution Explorer

If you look at your MonoGame project in the Solution Explorer, you will see a Content folder. Expand that, and you will find a Content.mgcb file, which defines all of the content that your game uses. You won’t have to edit this file directly.

By double-clicking on this Content.mgcb file, Visual Studio will open it up with the default editor for this type of file, which should be the external MonoGame Pipeline application that comes with MonoGame. (If this doesn’t work for you, you can right-click on it and choose Open With… to choose this and set it as the default.)

A screenshot of the MonoGame Content Pipeline management tool

This application is rather simple, but it has some nuances that we’ll look at over time. For now, a brief overview without all of the details is in order.

First thing’s first: You can save the .mgcb file, as well as create new ones and open other files from the File menu. Other than saving, most people’s workflow will lead you to open the file only through Visual Studio, so it might be somewhat rare to create new files and open files from this menu, but it’s there in case you need it.

We’ll use the Edit menu in a minute to add files to the content project. More on that in a minute.

While Visual Studio will build your content for you, if you’re sorting through content building problems, you might find the options on the Build menu useful, which will just build the content, and not your whole codebase.

Down in the main view are three windows. In the top left is the directory structure of your content. When we add content files, these will all appear here. And we’ll be able to add folders to manage them here as well.

On the bottom-left are the properties of the selected content file. We can use this to fine-tune some of the details of each of our content files, but in most cases, we won’t have to change much here. When we add files, the MonoGame content pipeline tool is smart enough to get the defaults configured correctly, and that’s usually sufficient.

On the right side is the output window. When you build your content project in the MonoGame Pipeline tool, you’ll see the results displayed here, showing you any errors that may come up during compilation.

OK. With all of that behind us, it’s time to look at how to add files to your game.

Adding Assets to your Project

MonoGame supports a wide variety of formats, and also allows you to extend the content pipeline if what you need isn’t already available. Below are some of the types that the MonoGame content pipeline supports:

Content TypeFile Types
3D Models.x, .fbx, .obj, .dae
Textures/Images.bmp, .dds, .dib, .hdr, .jpg, .pfm, .png, .ppm, .tga
Audio.xap (an XACT audio project), .wma, .mp3, .wav
Fonts.spritefont
Effects.fx

(I’d like the above table to be comprehensive, at least as far as what’s available out-of-the-box. If you’re aware of another file type that it supports natively but that isn’t listed here, please let me know.)

For most types of content files, you will have already created the file in a separate application. (An image editor like Photoshop or Inkscape, or a 3D modeling program like Wings 3D, Blender, or Maya, etc.)

For existing files, you can add these to your MonoGame content project by either choosing Edit > Add > Existing Item… from the menu, or right-clicking on the Content node in the tree view in the top left of the screen, and browsing to find the file.

The MonoGame Pipeline tool also lets you create a few different content files from scratch, rather than by adding an existing one. One primary candidate for this is when you want to add sprite fonts.

To add a new file (like a new sprite font file) you simply choose Edit > Add > New Item… from the menu or right-click on the Content node in the tree view in the top left of the screen, choose the type of new content you want to add, give it a name, and hit OK.

The image below shows a content pipeline file after adding a JPG image and a sprite font:

Content added to the project

In the upcoming tutorials, we’ll look at how to actually use this content in your game.

Organizing Content with Folders

You may find it useful to organize your content into folders. To add a folder, either go to Edit > Add > New Folder… from the menu, or right-click on the Content node (or parent folder) in the tree view in the top left of the screen and choose Add > New Folder. Give it a name in the dialog that comes up and hit OK. This will add the new folder to the tree view (and create a new folder on your disk).

As of MonoGame 3.8, the MonoGame Pipeline tool doesn’t let you drag files around between folders to move them. That’s a little frustrating because you have to move the file on the file system and then delete and re-add the file in the Pipeline Tool. But perhaps that’s something that will be fixed soon in another update.

Screenshot that shows folders

For the purposes of practicing how this works, and also to make sure that everything is working as it should, add an image into the content project now, before proceeding on.

Loading Content in MonoGame

OK, now we are on to the real interesting part. We are now going to use the content we just added. In other tutorials, as we talk about using each of the different kinds of content in turn, we will discuss this in greater detail. For now, though, we will just do something simple. Loading content in your game is always done in about the same way. Go to your LoadContent() method in your game, and add the following line (replacing [FileNameWithoutExtension] with the name of your file in quotes):

Texture2D image = Content.Load<Texture2D>("[FileNameWithoutExtension]");

A Texture2D object is simply a way of storing a picture. A texture is the computer graphics term for an image that you place on a 3D object, which is one of the most common ways of using an image. There are other ways to use a Texture2D object, as well. We will talk a little more about this in other tutorials. All we really need to do to load our content is call the function Content.Load(), with the name of the asset that we want to load. In the angle brackets (< and >) we put the type of content that we are loading, which in this case, is simply a Texture2D as well.

You do not need to put the extension on the file, though you’re allowed to if you want.

Also, if you have put your content in different directories, you will need to put the path to the file as well. For example, if our image was called Logo in a directory called Backgrounds, we would need to use:

Texture2D image = Content.Load<Texture2D>("Backgrounds/Logo");

Unloading Content in your Game

For a small game, you may not ever need to unload any content in your game. However, if you have a big game, you can’t just keep loading more and more content and expect it to keep working. It is a good idea to unload unnecessary content whenever you are done using it. So, for instance, you can unload all of the content for a particular level, after the level is completed, so that there is room for the next level’s content to be loaded.

To do this, simply add the following line to your program:

Content.Unload();

This frees up (almost) all of the content that was loaded by your content manager. Of course, this means that if you want to reuse something that was previously loaded, you will need to load it again.

It might be a good idea to create multiple ContentManager objects to divide up the content. That way you can call Unload() for the ContentManagers that you are done with.

Even if you don’t have a big game, it is still doesn’t hurt to unload unused content.

At this point, we’re now ready to begin making something a bit more real!