Embedding content as resources

Embedding content as resources

  • Comments 13

Reusable XNA components often contain content as well as code. For instance the bloom sample on the creators.xna.com site uses several custom effects, and the framerate component I described in my previous post needs a font to display the output.

If you are distributing a component in source form, people can just add the necessary content files to their project along with the component source code. If you distribute it as a game library project, adding that project to your game solution will even automatically copy the built content into the right output directory for you.

Things are less convenient if you want to distribute your component as a binary DLL, however. Not much fun for your users if you have to tell them "as well as adding this DLL to your project references, you also need to copy these three .xnb files to this particular directory where my component can find them".

The solution is to embed your content as resources directly inside the component DLL. This way you only need to distribute that one single file, which can include both code and content.

As a starting point, I'll assume you already have the framerate component from my previous post set up to build as a Game Library project. We need to add a second helper project to build the content, to make sure the content will be built before we try to embed it as a resource (there would be a circular dependency if the same project that was building the content was also trying to embed it).

Right-click on the solution node at the top of the Solution Explorer pane, choose Add / New Project / Windows Game Library, and enter "Content" as the project name. Delete the resulting Class1.cs file, because this helper project will only contain content, not code. To ensure the content is built first, right-click on the framerate component project, choose Project Dependencies, and check the entry for the content project.

Now you need to move the .spritefont file from the framerate component into the content project. You can do this by dragging in the Solution Explorer, which will make a copy, and then deleting the original file.

Build the content project, in order to create the output .xnb file.

Now create a resource file to embed the .xnb data. Right click on your framerate component project in the Solution Explorer, choose Add / New Item, and pick the "Resources File" template.

Double-click the resulting Resource1.resx to load it into the resource designer. From the toolbar at the top left of the designer, pull down the little arrow at the right of the Add Resource button and select Add Existing File. Browse into your Content/bin/x86/Debug directory, and select Font.xnb (if this doesn't show up, make sure the file selector filter is set to All Files).

Finally, you must tell the framerate component to load its content from the embedded resource rather than looking for an external file. Change this line:

    content = new ContentManager(game.Services);

to:

    content = new ResourceContentManager(game.Services, Resource1.ResourceManager);

And there you have it.

There is one major downside to embedding content as assembly resources, however. The entire assembly (including resource data) will be loaded into memory in one go, and the CLR does not provide any way to unload assemblies other than by unloading the entire AppDomain. This is no problem for components that just need a couple of small helper assets, but it probably wouldn't be a good idea to embed all your game levels and sounds in this way!

  • PingBack from http://nick.gravelyn.com/2008/06/19/releasing-zune-games-sans-source/

  • [quote]

    content = new ResourceContentManager(game.Services, Resource1.ResourceManager);

    [/quote]

    And with this line you made my day :-) thanks a lot!

  • how does this work with AudioEngine and .xgs files?

  • > how does this work with AudioEngine and .xgs files?

    It doesn't. XACT is a streaming technology, so it requires its assets to be in regular standalone disk files that it can stream from.

    The Song and Video types work the same way, for the same reason.

  • Does the XBox 360 support resource files?  Or are the .resx files only available on Windows?

  • > Does the XBox 360 support resource files?

    Sure. .NET assemblies work pretty much the same on all platforms that support the CLR.

  • Is there a way to automatically link the xnb generated to the Resource? I noticed that if any changes were made to the content file, you would have to manually update the Resources because it copies the xnb into it's own folder.

  • Never mind, I searched more into it and found out I can use the pre-build Command Line to copy the contents of a folder. At that point, as long as the Resource manager knows about the file it will update properly.

    This is my command used in the main library build command line.

    copy "$(SolutionDir)..\Content\Content\" "$(ProjectDir)Resources\"

  • Thanks Shawn,

    "Now you need to move the .spritefont file from the framerate component into the content project. You can do this by dragging in the Solution Explorer, which will make a copy, and then deleting the original file.

    Build the content project, in order to create the output .xnb file."

    Isn't there something missing here? How do you tell the file to be transformed into a .xnb? Say I have a texture, I don't have any content importer/process to tell the file to be transformed into the right .xnb

  • Steph,

    The source file is transformed into an .xnb when you build the content project. That's the whole point of the Content Pipeline: to build source assets into .xnb format as part of the Visual Studio build process. You don't need custom importers or processors as long as you are just using built-in types like textures or fonts that already have importers and processors.

  • But the content project you created is not a content pipeline but a Window game library.So when you build it you get a content.dll and not xnb files.

    Well, personnaly I create a Content project WITH a Content Pipeline, build it so I get the xnb files.

    Then in my dll I link those xnb in my Resources folders.

    It works great

    However it seems I have to create a Xbox specific content projects as Xbox generates a "wrong platform" error from those xnb

    Is that normal? Indeed it seems you posted that it should work on xbox as well

  • Steph: .xnb format is different for every target platfom, so if you are making an Xbox game, you must build the content for Xbox platform rather than Windows.

  • is there any other way to embed contents on website?

Page 1 of 1 (13 items)
Leave a Comment
  • Please add 3 and 5 and type the answer here:
  • Post