Loading content - best practice?

I know this is somewhat of an old subject but I cant seem to find an absolute answer.

According to the XNA documentation you should “Load all your game content” via the Game.LoadContent() method. I know that I could make multiple contentmanagers, only load what i need when i need it etc - but lets leave that discussion for another day. Lets stick with the fact that XNA wants you to load your content via the LoadContent method and not in the Initialize method.

My problem with this is that I may want to load the content in another or several other classes. Now, these classes will obviously not work without first having all content loaded. At the same time, these classes “should” be instantiated in the Game.Initialize() method.

Something like this:

    protected override void Initialize()
    {
        _gameView = new GameView()
        base.Initialize();
    }

    protected override void LoadContent()
    {
        _gameView.LoadContent(Content)
        base.LoadContent();
    }

From a pure C# perspective, this creates a problem, since you know have a manditory method that is not the constructor - that needs to be called once before anything else is performed in the class. It’s just obvious bad .Net/C# practice.

I would much rater just pass the content manager in the constructor:

    protected override void Initialize()
    {
        _gameView = new GameView(Content)
        base.Initialize();
    }

Is this considered bad practice? Are there any true different between loading your content in the Initialize method rather than in LoadContent?

Some might say I could just create the class instance in the LoadContent method. But then you bypass the intention of Game.Initialize where you according to documentation should “load any non-graphical resources” - aka Classes.

I ran into this also.

My solution was to pass the content manager to the class Initialize() method.

    public void Initialise(ContentManager content)
    {
        mapTexture = content.Load<Texture2D>("Graphics/MyMap");

It’s not ideal but it was good enough for me.

It’s common C# design to pass “services” or controllers" to the constructor, but that doesn’t mean you still can’t load in LoadContent. Try this

    protected override void Initialize()
    {
        _gameView = new GameView(Content)
        base.Initialize();
    }

    protected override void LoadContent()
    {
        _gameView.LoadContent();
        base.LoadContent();
    }

If you want to more about what is good practice regarding such things you may want to read up on the principles of Inversion of Control (IoC) and Dependency Injection (DI), which are also useful for when you do unit testing in C# if you’re interested. Although to achieve full IoC you’ll want to wrap parameter arguments as interfaces which might be a hassle if it’s just a fun hobby project

In your first example what you did was similar to method injection

My example is similar to constructor injection.

Not following here =) The default content manager is already available in Game.Initialize.

That is a variant. However, the issue is still there since LoadContent still needs to be called before any other methods in the class that might use any content. Lets say, Update or Draw methods. After an initialization of a certain class - you should be able to assume that you can call any public method without any errors.

What I would want, is some sort of framework Interface or baseclass that is “hooked up” to the load-event - that my content based classes then could inherit or use.

public class GameView : IContentLoad

or something in that line.

That is a variant. However, the issue is still there since LoadContent still needs to be called before any other methods in the class that might use any content. Lets say, Update or Draw methods.

Excuse me what are you saying? LoadContent is called before the first Update and Draw calls so what I proposed doesn’t have the issue you’re talking about

What I would want, is some sort of framework Interface or baseclass that is “hooked up” to the load-event - that my content based classes then could inherit or use.

That works. In my project I have a interface for the xna game loop methods, Intitilise, LoadContent, Update, and Draw. Then I have a collection of game entities that I iterate over in the Game class and run the specific methods at the right time. https://github.com/LateStartStudio/Hero6/blob/master/src/Hero6.Engine/MonoGame/GameLoop/IXnaGameLoop.cs

He means into a separate class for loading content.

Yes I think I originally wanted to pass the Content to the constructor but that meant I couldn’t instantiate the class until after Content was setup.

So I compromised by passing it to Initialise() which is called after Content is setup.

Yes, in the XNA framework LoadContent is always called before Update/Draw. But as i said, from a pure C# perspective it becomes somewhat bad practice to do it this way. Lets say i make an engine for others to use in XNA. They make an instance of one of the engines classes. After they make this instance - they should be able to assume that all of its public methods now can be used.

With a LoadContent method inside this class - that has to be called from the games LoadContent method - that is not the case. They then have to know that LoadContent must be called before they can use the class.

Maybe Im complicating things by trying to combine XNA best practice with pure C#/.Net best practice =) Figured some big brains would have figured it out =P

What you’re mentioning here doesn’t really have anything to do with “pure C#” whatever that means, it depends on the use cases you want to satisfy (reusability, security, performance, extendibility etc.), in your case you want a clean public API that doesn’t require a long instruction manual to go with it.

There are many ways to do this, I’m going to mention 2 that comes to mind, one simple, and one more complicated.

Simple:
Make your game entities use 2 interfaces like this

public class GameView : ILoadContent, IGameViewAPI
{
}

This way the XNA stuff and your API is split between 2 interfaces right? Internally in your engine you can call the LoadContent method, you can then serve the IGameViewAPI to your engine users, and they don’t even have to know that engine was made in XNA/MonoGame at all from a code perspective.

More complex:
You can have a model, and split the implementation of the engine and the API in 2 different classes.

public class GameView
{
    // Basic data in this class
}

internal class GameViewEngine : ILoadContent
{
     public GameViewEngine(GameView) gameView ...
}

public class GameViewAPI : IGameViewAPI
{
    public GameViewAPI(GameView gameView) ...
}

Serve the GameViewAPI to the consumers of your engine and you can do MonoGame stuff in the GameViewEngine. They both share state and information through the data in the GameView instance.

If you’re going to into this kind of organization it’s a good idea to read up on software design patterns, knowing those will allow you to solve problems exactly like this.

1 Like

“pure C#” whatever that means

Sorry for using unclear terms. By “pure c#” Im talking about general “best practices” in terms of the c# language and .Net framework. Managed Recommended Rules rule set for managed code - Visual Studio (Windows) | Microsoft Learn for example.

I read somewhere that you can load your content anytime after the GraphicsDevice have been initialized. LoadContent gets called after that - so that is why it is designed to be used for loading content.

However, you could just as well load your content just about anywhere as long as the Graphics Device has been loaded - for example later in the Initialize method. Can someone confirm this =)?

Yes, you can load anytime if you want to customize your loading, for example if your game is divided into modules you can load the modules you need, and not load the other modules until the player accesses them.