1
\$\begingroup\$

Currently I'm using XNA's ContentManager to load my content. For the unfamiliar the ContentManager deserializes classes from disk and keeps a reference for future requests.

I'm currently facing a problem with management, where for some resources I don't want to deserialize them repeatedly (e.g. a texture) but for others I do (e.g. destructible level geometry). As it is now when I replay a level I get back the original class with the player's changes.

For this reason I decided to inherit from ContentManager to provide some way of re-deserializing a resource to get a new copy (probably using the protected ReadAsset<T> method).

Now I'm thinking about how I should manage this. Ideally I want some way of saying you can re-use Textures, but not Levels (i.e. when a Level is requested it always deserializes a new instance).

While I think about that I'd also like to create my custom ContentManager with a view to get other niceties such as automatic unloading, on-demand or in advance loading of assets, pre-loaded place-holder assets etc.

How is this sort of class typically designed and how can I overcome my immediate problem (reloading particular types and re-using instances of others)?

\$\endgroup\$

3 Answers 3

1
\$\begingroup\$

It sounds to me like ContentTracker has what you require. It allows for disposing and reloading of individual items, among many other things.

It should be what you're looking for, I think.

(Do note, that it's for XNA 3.1 only, however there is a link at the bottom of the Codeplex homepage where someone has kindly ported it to 4.0)

\$\endgroup\$
1
\$\begingroup\$

If I rembemer correctly, caching assets is done in Load method. So all you need to do is override this metod, and make custom caching (store loaded asset in dictionary with assetName as key). (This will help you later in unloading only certain items).

And then make new method LoadNew which will bypass caching (or create clone)

\$\endgroup\$
1
\$\begingroup\$

update

After a bit of a chat with Kikaimaru, I realized the deep copy wont work as seamlessly as I thought. Too bad, I thought it was very elegant. The methods below will still work though.


If you are still set on doing it, try something like this. Just overload the method telling it to cache or not. I pretty much snagged this from this blog, and he goes into more detail there. You might find it useful should you decide to go this way.

public override T Load<T>(string assetName)
{
    return Load<T>(assetName, true);
}

public T Load<T>(strng assetName, bool cache)
{
    if (loadedAssets.ContainsKey(assetName))
        return (T)loadedAssets[assetName];

    T asset = ReadAsset<T>(assetName, null);

    if(cache)
        loadedAssets.Add(assetName, asset);

    return asset;
}

I had another thought. What you could do it something along the lines of creating an interface to make all your non-cacheable object implement. Have the load manager look for that, and don't cache if it is found. You could accomplish the same thing with an attribute if you wanted.

public interface INoCache{} //no member here, just empty...Maybe a bool "ShouldCache" if you want...

public class Destructible : INoCache

//In your ContentManager
public T Load<T>(string assetName)
{
    if (loadedAssets.ContainsKey(assetName))
        return (T)loadedAssets[assetName];

    T asset = ReadAsset<T>(assetName, null);

    //this logic seems a bit backwards, but 
    //it makes for a little cleaner code IMHO
    if(!(asset is INoCache))
        loadedAssets.Add(assetName, asset);

    return asset;
}
\$\endgroup\$
7
  • \$\begingroup\$ Are you sure you can make copies like that of things like texture or vertex buffer, that has pointer to some unmanaged directx stuff? \$\endgroup\$
    – Kikaimaru
    Apr 25, 2012 at 16:23
  • \$\begingroup\$ I could very well be wrong as I have never done it, but I think it is the other way around. The Texture2d is just a location in memory. doing a deep copy just creates a perfect clone in another location essentially doing what you want. the DX stuff will have pointers to THAT location in memory. \$\endgroup\$
    – user159
    Apr 25, 2012 at 16:29
  • \$\begingroup\$ Yes, it will have pointer to that vertex buffer in unamanged memory. And when he will try to edit it (destructible geometry), it would affect all meshes that has pointer to that vertex buffer. (Well but I don't know where vertex buffer data are stored, and where do dynamic vertex buffer store them) so it's just a thought. \$\endgroup\$
    – Kikaimaru
    Apr 25, 2012 at 16:54
  • \$\begingroup\$ @Kikaimaru To plays devil's advocate, where did you hear this? Using the second or third method above is doing essentially the same thing. You are creating a second copy of the entire data structure. I can do that via loading from disk or re-serializing it again in memory and it shouldn't matter. Both ways cause me to create a new copy of the whole object. No offense here (and I could be 100% wrong) but you do know what I mean by deep copy right? I'm not talking about a shallow copy. \$\endgroup\$
    – user159
    Apr 25, 2012 at 16:58
  • 1
    \$\begingroup\$ let us continue this discussion in chat \$\endgroup\$
    – Kikaimaru
    Apr 25, 2012 at 17:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .