Working with new Content Builder Projects
Learn how to use the newest approach to building content in MonoGame without the legacy MGCB-Editor.
Note
These instructions REQUIRE you to use the latest MonoGame Preview release (currently 3.8.5-preview.6)
See the instructions here for how to install the preview project templates and update your project to use 3.8.5-preview (preview) releases.
The MonoGame Content Pipeline is a powerful tool for packaging and managing all the complex needs for working with and distributing assets in your MonoGame projects, solving all the complexities surrounding the use of assets on all the platforms that MonoGame supports.
From MonoGame 3.8.5 we are making a new Console Project Style solution to more effectively manage your content in source to reduce complexity (and installation demands) and put control of your source assets fully within your control.
Important
This documentation is a work in progress and subject to change.
While every effort will be made during the 3.8.5 preview to keep this documentation up to date, check back often for reference and log issues for corrections to assist the team in its development.
Table of Contents
- What is the Content Builder?
- Getting Started
- Adding the Content Builder Project to your Game
- Understanding ContentBuilderParams
- Creating Your ContentCollection
- Including and Excluding Content
- Working with Importers and Processors
- Advanced Scenarios
If you prefer, the MonoGame Foundation recorded a short video demonstrating how to get set up with the new Content Builder Project.
What is the Content Builder?
The Content Builder is a powerful tool that allows you to build game content (like images, sounds, fonts, and models) programmatically using C# code instead of manually configuring content files. Think of it as your own personal content pipeline that you control entirely through code!
Instead of an installed dotnet tool (which historically generated issues), the new approach uses a simple Console application you manage, which is simply executed to build and generate your content. It builds all configured content from the designated "Assets" folder and compiles it using the default importers used by MonoGame. To customize this, you only need to specify additional commands to override this default behaviour with your customizations.
Tip
When designing the builder for your content, try to focus on building patterns for your content to reduce the need to rebuild the Builder itself.
In an ideal scenario, you build the Builder once, then just keep adding assets and running the builder to produce the runtime content, identifying "early on" any issues with your assets and simplifying production.
In addition, due to content now being built through your own console application, it is easily distributable and can even be used in automation pipelines in source control.
Features provided with the new Content Builder project
- Automation: Build content as part of your build process.
- Flexibility: Apply complex rules to determine which files get processed.
- Control: Fine-tune how each asset is imported and processed.
- Integration: Perfect for tools, editors, and custom-built pipelines.
- Customization: Inject additional capabilities into your asset management as required.
Tip
Yes, it is completely possible, through automation, to have your Content and Game EXE/deliverables built separately, and then simply combined later when packaging the solution.
We will look to provide more guides in the future to showcase this capability.
Getting Started
To start using the Content Builder, you will need to create a console project using the MonoGame Content Builder template. Here are instructions to create your own Content Builder Project:
To add the class library using the MonoGame Content Builder project template in Visual Studio Code, perform the following:
- In the Solution Explorer panel, right-click the solution.
- Choose New Project from the context menu.
- Enter "MonoGame Content Builder" and select it as the template to use.
- Name the project "MyContentBuilder".
- When prompted for a location, use the default option, which will put the new project in a folder next to your game project.
- Select "Create Project".
This creates a project with the following structure:
MyContentBuilder/
├── Builder/
│ └── Builder.cs # Your custom builder class
├── Assets/
│ └── readme.txt # Placeholder text file to be replaced with your content
├── BuildContent.targets # Shared .targets file for content building
└── MyContentBuilder.csproj # Project file with required packages
This is the default (recommended) layout for a Content Builder project, but you can customize its use how you wish:
- There is a single "entry point" (command line launch point) contained in the
Builder.cswhich contains all the instructions to build content. - A default
Assetsfolder to host your content, but your content can be in any location you need it to be, simply update the parameters used to run the console application to point to the source directory and folder for your content.
Tip
While it is possible to include the builder as part of your game code, rather than a separate project, at this time we do not recommend this. Based on experience, it is always better to build your content separate from your runtime game to avoid collisions or issues arising in game production/deployment.
Adding the Content Builder Project to your Game
Once you have created your Builder project, you have two options:
- After building your game, you need to copy the build output from the Builder to the output of the Game, so the
exeand thecontentfolder are in the same output folder. - Add a
Targetdefinition to yourcsprojto automatically copy the Builder output to the game output when the project is built (like how the current MGCB solution works)
This section will focus on Option 2 to replicate what happens in 3.8.4 projects.
1. Clean up redundant files
As the Content Builder project is NOT a DotNet tool, you no longer need the dotnet-tools.json configuration.
- Remove any
.configfolders from your solution that containdotnet-tools.jsonfiles.
2. Remove legacy MGCB references from your csproj
As you would expect, we no longer need any old Content references or tools for building that content, aka, the MonoGame.Content.Builder.Task reference.
Per platform/game project:
- Remove any
MonoGameContentReferenceelements from your game'scsproj. - Remove references to
MonoGame.Content.Builder.Task. - Update the MonoGame version to match the Builder (not essential, but recommended)
3. Add the Builder Import task
To complete the process, add the following Import section to your csproj (before the final </Project> entry):
<Import Project="..\Content\BuildContent.targets" />
Platform specific additions - Android / iOS
For platforms where the content is required to be packaged inside the output bundle, which require additional steps to ensure the built content is included during the Build/Publish step.
Thankfully, these steps are now handled inside the BuildContent.targets task, replicating how the legacy MGCB build process handled it. No action needed on your part.
Basic Builder Project Structure
The default Builder.cs file looks as follows, which demonstrates how to selectively add content from the designated Assets folder using the default Importers and Processors (how MonoGame compiles content) into processed .XNB files for consumption by your runtime project:
using Microsoft.Xna.Framework.Content.Pipeline;
using MonoGame.Framework.Content.Pipeline.Builder;
// Console program entry point, make a new builder and run using commandline arguments
var builder = new Builder();
builder.Run(args);
return builder.FailedToBuild > 0 ? -1 : 0;
public class Builder : ContentBuilder
{
public override IContentCollection GetContentCollection()
{
var contentCollection = new ContentCollection();
// By default, no content will be imported from the Assets folder using the default importer for their file type.
// Please define your content collection rules here.
/* Examples
// Import all content in the Assets folder using the default importer for their file type.
contentCollection.Include<WildcardRule>("*");
// Only copy content from the assets folder rather than build it with the pipeline.
contentCollection.IncludeCopy<WildcardRule>("*.json");
// Exclude assets that match the pattern., only required overriding a default import behaviour.
contentCollection.Exclude<WildcardRule>("Font/*.txt");
// Include a specific asset with processor parameters.
contentCollection.Include("Models/character.glb", new FbxImporter(),
new MeshAnimatedModelProcessor()
{
Scale = 100.0f
}
);
*/
return contentCollection;
}
}
The comments are a basic guide to walk you through the basics for identifying content in your projects Assets folder and queuing them up for processing during the Content Build phase.
Recommendations
- Try to group assets with similar processing together, e.g. All audio in the same folder
- Any assets requiring special processing or specific content importers should be grouped together in the same folder.
- Make sure any files that require copying rather than building use the
IncludeCopycommand. - Any content that cannot or should not be processed, needs to be either outside one of the folders configured, or specifically excluded using the
Excludecommand.
Important
Rule - Last one at the door stands
Whatever the state of a file is by the END of the Content Collection configuration, wins. You can do a broad Include for Everything and then exclude items after it, updating those items queue state. (If you do it the other way round, then with Include being last, everything is included)
Understanding ContentBuilderParams
ContentBuilderParams defines the operational configuration that tells the Content Builder where to find your content, where to output it, and how to process it. Think of it as the "settings panel" for your content building operation.
Core Properties
Here are the main properties available to work with:
| Property | Description | Default Value |
|---|---|---|
WorkingDirectory |
The root directory for all operations | Current directory |
SourceDirectory |
Where your source assets are located | "Content" |
OutputDirectory |
Where built content will be saved | "bin/Content" |
IntermediateDirectory |
Where temporary build files go | "obj/Content" |
Platform |
Target platform for the content | TargetPlatform.DesktopGL |
GraphicsProfile |
Graphics capability level | GraphicsProfile.HiDef |
CompressContent |
Whether to compress output files | false |
LogLevel |
How much information to display | LogLevel.Info |
Rebuild |
Force rebuild all content (ignore cache) | false |
Creating ContentBuilderParams
Option 1: Direct Initialization
var contentParams = new ContentBuilderParams()
{
Mode = ContentBuilderMode.Builder,
WorkingDirectory = $"{AppContext.BaseDirectory}../../",
SourceDirectory = "Assets",
OutputDirectory = "bin/DesktopGL/Content",
Platform = TargetPlatform.DesktopGL,
GraphicsProfile = GraphicsProfile.HiDef,
CompressContent = false,
LogLevel = LogLevel.Info
};
Option 2: From Command Line Arguments
var contentParams = ContentBuilderParams.Parse(args);
This parses command line arguments like:
mybuilder.exe --src "MyAssets" --output "bin/Content" --platform DesktopGL --compress
Understanding Directory Paths
The directory paths work together to organize your content:
Important
The WorkingDirectory should always be fixed path or directly resolvable from the application's execution path, which CAN be different based on whether the console application is run in release or debug mode. The default path provided uses a relative path from the point of execution. If in doubt, test with an absolute path and work back from there.
WorkingDirectory/ # Your project root
├── SourceDirectory/ # Input: Your raw assets (images, sounds, etc.)
│ ├── Textures/
│ └── Audio/
├── OutputDirectory/ # Output: Built .xnb files ready for your game
│ ├── Textures/
│ └── Audio/
└── IntermediateDirectory/ # Temporary: Cache and build information
└── cache/
Important Note: Paths can be absolute or relative to the WorkingDirectory.
Creating Your ContentCollection
The ContentCollection is where you define the rules for how your content should be handled. It is like creating a recipe book that tells the Content Builder what to do with each file.
Basic ContentCollection Setup
public override IContentCollection GetContentCollection()
{
var contentCollection = new ContentCollection();
// Only effect files from the Effects folder
contentCollection.Include<WildcardRule>("Effects/*.fx");
// Only spritefonts from the Fonts folder (not ttf)
contentCollection.Include<WildcardRule>("Fonts/*.spritefont");
// Only import PNG files from the Textures Folder
contentCollection.Include<WildcardRule>("Textures/*.png");
contentCollection.Include("splash-screen.png");
return contentCollection;
}
By default nothing is imported via the builder, like the MGCB editor before it, you need to selectively add content to your assets folder and then update the Builder. But to make it easy on yourself, organise content by rules:
- Textures in one folder
- Audio in another
- Files needing special processing or custom importers in their own folder
Then configure the builder to look for that kind of content in those folders. By that rule, any content you add will not require you to rebuild your Content Builder exe and you can just run it to process your asset folder for your game.
Note
If in doubt, you can always just use the following default "include everything" rule and then exclude anything that cannot be processed:
contentCollection.Include<WildcardRule>("*");
But we recommend managing your content, like you manage your game, so that everything is always where you expect it.
Including and Excluding Content
The ContentCollection provides flexible ways to specify which files should be processed and how, any files that cannot be compiled will be reported in the console output.
Any additional ContentCollection commands provided after the global include simply update the "processing" list, as all content is only built ONCE (per folder).
Understanding Rule Order
Important: Rules are evaluated in order, and the last matching rule wins!
Note
Rules simply update the processing order for each file. Whatever the last rule applied to affect the file/folder definition is, is the final state in which a file will be processed. If you are not getting the output you expect, you can output the collection to file and examine it for reference, then check WHY a file was in its final state.
For example, the following rule order shows that all png files are included for processing initially, but then a later rule updates this and specifically excludes png files from processing. The result, no png files are processed and they are ignored:
// Include all PNG files
contentCollection.Include<WildcardRule>("*.png");
// But exclude debug files
contentCollection.Exclude<WildcardRule>("*debug*.png");
// Result: All PNG files EXCEPT those with "debug" in the name
Simple File Inclusion
If you want to do it the hard way, you can specify individual rules for including / updating content to be built, specifying specifically how the file should be processed, to which folder/file and how it should be processed.
Note
Note the "Copy" rule, there are situations in content where you simply DO NOT want the file to be processed, only copied to the output folder, normally where there is additional processing required at runtime.
MonoGame does recommend using custom Importers and Processors to handle custom content, especially XML, TXT, or JSON files, as issues with content can be identified earlier when content is built (and not when your game runs, and then invariably crashes)
Include a Single File:
// Build a specific texture
contentCollection.Include("Textures/hero.png");
// Copy a file without processing
contentCollection.IncludeCopy("Data/config.json", "config.json");
With Custom Output Path:
// Save to a different location
contentCollection.Include("Sprites/player.png", "Characters/Player.xnb");
Pattern-Based Inclusion
The recommended pattern to use is to group your content either by folder or type and then use Wildcards to collectively refer to how content should be processed, e.g. all images in this folder should be processed in this way, rather than file by file.
Using Wildcards
Wildcards are perfect for matching multiple files with simple patterns:
// Include ALL files
contentCollection.Include<WildcardRule>("*");
// Include all PNG files
contentCollection.Include<WildcardRule>("*.png");
// Include all files in Textures folder
contentCollection.Include<WildcardRule>("Textures/*");
// Include all PNG files in any subfolder
contentCollection.Include<WildcardRule>("*/*.png");
// Include specific file types
contentCollection.Include<WildcardRule>("*.{png,jpg,bmp}");
Wildcard Pattern Reference:
| Pattern | Matches |
|---|---|
* |
Any sequence of characters |
? |
Any single character |
[abc] |
Any character in the set |
[!abc] |
Any character NOT in the set |
{a,b,c} |
Any of the alternatives |
Using Regular Expressions
For more complex patterns, use regular expressions:
Note
Be wary, RegEx expressions are a dark art and may behave differently depending on the language used. Use tools like regex101 (an online regex tester tool) to verify and check your search results, but note they have been known to operate differently based on OS/Language at runtime.
// Match files ending with _diffuse.png
contentCollection.Include<RegexRule>(@".*_diffuse\.png$");
// Match numbered files
contentCollection.Include<RegexRule>(@"level_\d+\.tmx");
// Match files in specific folders
contentCollection.Include<RegexRule>(@"^(Textures|Sprites)/.*\.png$");
Excluding Content
Sometimes you need to exclude certain files from processing:
Note
This prevents the Content Builder from doing anything with a file and effectively ignores it, useful for associated files (like .ttf font files usually included alongside a .spriteFont descriptor) that do not need processing as they are consumed by another content process.
Exclude Specific Files:
// Exclude a specific file
contentCollection.Exclude("Textures/debug_texture.png");
// Exclude multiple files
contentCollection.Exclude("Textures/test_01.png");
contentCollection.Exclude("Textures/test_02.png");
Exclude Using Patterns:
// Exclude all files starting with "test_"
contentCollection.Exclude<WildcardRule>("test_*");
// Exclude all files in Debug folder
contentCollection.Exclude<WildcardRule>("Debug/*");
// Exclude backup files
contentCollection.Exclude<RegexRule>(@".*\.bak$");
// Exclude temporary files
contentCollection.Exclude<RegexRule>(@".*~$");
Advanced Pattern Examples
As stated, it is recommended to define patterns for your content, defining rules for processing your content (and preventing changing/rebuilding the Content Builder exe), the following are examples of such patterns, grouping specific content into specific folders.
Note
There are no predefined rules for how you organize your content, it is completely up to you and the needs of your project to determine how it is best organized. Just make sure to include decisions on how to ease the burden of managing the importing content in those decisions so that you do not need to frequently keep updating your Builder.
Set it once, and then you have strict rules for how content is processed and errors should be easily identifiable.
Organize by File Type:
var contentCollection = new ContentCollection();
// Images
contentCollection.SetContentRoot("Graphics");
contentCollection.Include<WildcardRule>("*.{png,jpg,bmp}");
// Audio
contentCollection.SetContentRoot("Audio");
contentCollection.Include<WildcardRule>("*.{wav,mp3,ogg}");
// Fonts
contentCollection.SetContentRoot("Fonts");
contentCollection.Include<WildcardRule>("*.spritefont");
// Everything else (copy as-is)
contentCollection.SetContentRoot("Data");
contentCollection.IncludeCopy<WildcardRule>("*.{xml,json,txt}");
Custom Output Paths with Functions
If you wish, you can also transform file paths dynamically:
// Flatten directory structure
contentCollection.Include<WildcardRule>(
"Textures/**/*.png",
outputPath: filePath => Path.GetFileName(filePath)
);
// Add prefixes
contentCollection.Include<WildcardRule>(
"*.png",
outputPath: filePath => $"processed_{filePath}"
);
// Reorganize structure
contentCollection.Include<WildcardRule>(
"Source/*/icon.png",
outputPath: filePath => {
var folderName = Path.GetDirectoryName(filePath);
return $"Icons/{folderName}_icon.xnb";
}
);
Working with Importers and Processors
Importers and processors are the heart of the content pipeline. They determine how your raw assets are transformed into game-ready content and built to meet the needs for each target platform.
Important
Different platforms have different requirements for content and while you can manage it yourself by packaging and loading it manually, this usually leads to complicated scenarios, especially when targeting consoles.
What are Importers and Processors?
- Importer: Reads your source file (e.g., PNG, WAV) and converts it into an intermediate format
- Processor: Takes the imported data and processes it into the final game format, sometimes including additional content or textures identified by the Importer. (Such as the skinned model importer)
Default Behavior
By default, MonoGame automatically selects the appropriate importer and processor based on file extension:
// MonoGame will automatically use:
// - TextureImporter for .png files
// - TextureProcessor to create the final texture
contentCollection.Include("hero.png");
Specifying Custom Importers and Processors
Sometimes you need more control. Here is how to specify which importer and processor to use and override the default behaviour:
Using Built-in Processors:
// Texture with specific processor
var textureImporter = new TextureImporter();
var textureProcessor = new TextureProcessor();
contentCollection.Include("hero.png", textureImporter, textureProcessor);
// Audio with specific processor
var audioImporter = new WavImporter();
var audioProcessor = new SoundEffectProcessor();
contentCollection.Include("explosion.wav", audioImporter, audioProcessor);
Note
As can be seen in the updated examples using the new Content Builder Project system, this can also be simplified to just:
contentCollection.Include("hero.png", new TextureImporter(), new TextureProcessor());
It just depends on which pattern you are more comfortable with.
Pattern-Based with Custom Processors:
This can also be used with pattern-based logic, applying the specified Importer/Processor to a group of assets:
// Apply texture processor to all PNG files
var textureImporter = new TextureImporter();
var textureProcessor = new TextureProcessor();
contentCollection.Include<WildcardRule>(
"*.png",
contentImporter: textureImporter,
contentProcessor: textureProcessor
);
// Apply font processor to all sprite fonts
var fontImporter = new FontDescriptionImporter();
var fontProcessor = new FontDescriptionProcessor();
contentCollection.Include<WildcardRule>(
"*.spritefont",
contentImporter: fontImporter,
contentProcessor: fontProcessor
);
Handling Custom Importer / Processor caching
The caching validation process that determines whether the Content Builder re-processes content by default is decided by:
- The comparison between the last state of the built asset and the source
- It will also take into account the "Version" of the Content Importer and Processor that was used at the time the content was built.
The cache is only invalidated when either of these conditions are met, else it will skip over processing of the asset for performance as it has not detected a change.
Note
MonoGame manages the versions of the built-in Importers and Processors, so unless MonoGame makes changes to these elements, the cache will not be invalidated unless you Force a rebuild.
If you want content to be rebuilt when a Custom Importer or Processor has changed (content that uses the custom entities in its builder configuration), then the version of the Custom Content Pipeline Extension has to change, to do this, simply update the "Version" property on the respective Importer or Processor as follows:
public override string Version { get; set; } = "new Version";
Note
The version can be anything you like, so long as it is a recognisable and readable string. Preferably something you can increment.
Configuring Processor Parameters
Many processors have configurable parameters that control how they process content. If you need to override these parameters with specific values, here is how to customize them:
Example: Texture Processing Options
var textureImporter = new TextureImporter();
var textureProcessor = new TextureProcessor
{
ColorKeyColor = Color.Magenta, // Transparent color
ColorKeyEnabled = true, // Enable color keying
GenerateMipmaps = true, // Create mipmaps
PremultiplyAlpha = true, // Premultiply alpha
ResizeToPowerOfTwo = false, // Keep original size
TextureFormat = TextureProcessorOutputFormat.Color
};
contentCollection.Include<WildcardRule>(
"Sprites/*.png",
contentImporter: textureImporter,
contentProcessor: textureProcessor
);
Example: Audio Processing Options
var audioImporter = new WavImporter();
var soundProcessor = new SoundEffectProcessor
{
Quality = ConversionQuality.Best
};
contentCollection.Include<WildcardRule>(
"SoundEffects/*.wav",
contentImporter: audioImporter,
contentProcessor: soundProcessor
);
Example: Font Processing Options
var fontImporter = new FontDescriptionImporter();
var fontProcessor = new FontDescriptionProcessor
{
PremultiplyAlpha = true,
TextureFormat = TextureProcessorOutputFormat.Color
};
contentCollection.Include<WildcardRule>(
"Fonts/*.spritefont",
contentImporter: fontImporter,
contentProcessor: fontProcessor
);
Advanced Scenarios
The following scenarios are of a more advanced nature for scenarios where you need specific customisation to suit your delivery needs.
Scenario 1: Platform-Specific Content
Build different content for different platforms:
Note
By default, content will be formatted specifically for the platform it is built for. This example is only where you might swap content based on the platform, e.g. for different quality sizes, store requirements or controller references. All to make the runtime project simpler to manage.
public override IContentCollection GetContentCollection()
{
var contentCollection = new ContentCollection();
if (Parameters.Platform == TargetPlatform.DesktopGL)
{
// High-quality textures for desktop
var processor = new TextureProcessor
{
GenerateMipmaps = true,
TextureFormat = TextureProcessorOutputFormat.Color
};
contentCollection.Include<WildcardRule>("*.png",
contentProcessor: processor);
}
else if (Parameters.Platform == TargetPlatform.Android)
{
// Compressed textures for mobile
var processor = new TextureProcessor
{
GenerateMipmaps = true,
TextureFormat = TextureProcessorOutputFormat.DxtCompressed
};
contentCollection.Include<WildcardRule>("*.png",
contentProcessor: processor);
}
return contentCollection;
}
Scenario 2: Multi-Language Content
Organize content by language:
Note
MonoGame recommends using a custom localized importer for language-specific content, this example serves only as an alternative strategy for handling localization.
public override IContentCollection GetContentCollection()
{
var contentCollection = new ContentCollection();
string language = "en"; // Get from configuration
// Default content
contentCollection.Include<WildcardRule>("Common/*");
// Language-specific content
contentCollection.SetContentRoot("Localized");
contentCollection.Include<WildcardRule>($"Languages/{language}/*");
return contentCollection;
}
Scenario 3: Dynamic Content from External Sources
Process content from multiple sources:
public override IContentCollection GetContentCollection()
{
var contentCollection = new ContentCollection();
// Base game content
contentCollection.Include<WildcardRule>("BaseGame/*");
// DLC content (if available)
var dlcPath = Path.Combine(Parameters.RootedSourceDirectory, "DLC");
if (Directory.Exists(dlcPath))
{
contentCollection.SetContentRoot("DLC");
contentCollection.Include<WildcardRule>("DLC/*");
}
// Mod content (if available)
var modPath = Path.Combine(Parameters.RootedSourceDirectory, "Mods");
if (Directory.Exists(modPath))
{
contentCollection.SetContentRoot("Mods");
contentCollection.Include<WildcardRule>("Mods/*");
}
return contentCollection;
}
Debugging
At times you might need to debug your Content Builder, and while you can just run it manually in debug mode and attach your IDE to it, sometimes it is also valuable to FORCE the application to pause and let you step through importing and processing, especially when working with Content Pipeline Extensions.
Alternatively, you may simply want to inject additional assets into your project for debugging purposes (such as overlays, etc) which are only consumed in a Debug build of your project (using #if DEBUG in your runtime too).
Note
This is a rather advanced area which for most situations you do not need to go to these lengths.
The following scenarios outline these options as they pertain to the Content Builder solution:
Scenario 1: Debugging the Builder
If you wish to inject a Debugger breakpoint to determine the cause of any issues when building content, you can add the following before the Builder runs in your Content Builder project, this will cause DotNet to request to launch the default debugger and automatically attach it to the project when it is run:
#if DEBUG
using System.Diagnostics;
#endif
// If you need to debug the content build process you can enable
// this, build the game, then attach the debugger when prompted.
#if DEBUG
Debugger.Launch();
#endif
// Launch point
builder.Run(args);
Scenario 2: Conditional Debug Content
Useful when you need to include extra content in debug only builds for testing, e.g. texture overlays or additional fonts:
public override IContentCollection GetContentCollection()
{
var contentCollection = new ContentCollection();
// Always include game content
contentCollection.Include<WildcardRule>("GameAssets/*");
#if DEBUG
// Include debug visualizations only in debug builds
contentCollection.SetContentRoot("Debug");
contentCollection.Include<WildcardRule>("DebugAssets/*");
#endif
return contentCollection;
}
Summary
The MonoGame Content Builder provides a powerful, flexible way to build your game content programmatically. Here are the key takeaways:
- ContentBuilderParams configures where and how content is built.
- ContentCollection defines rules for which files to process.
- Include/Exclude methods with patterns give you precise control.
- Importers and Processors can be customized for your needs.
- Rule order matters - the last matching rule wins!
With these tools, you can create sophisticated content build pipelines that adapt to different platforms, languages, build configurations, and project structures.
Happy content building!