Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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)?

share|improve this question
add comment

3 Answers

up vote 1 down vote accepted

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)

share|improve this answer
add comment

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)

share|improve this answer
add comment

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;
}
share|improve this answer
    
Are you sure you can make copies like that of things like texture or vertex buffer, that has pointer to some unmanaged directx stuff? –  Kikaimaru Apr 25 '12 at 16:23
    
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. –  Joe Apr 25 '12 at 16:29
    
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. –  Kikaimaru Apr 25 '12 at 16:54
    
@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. –  Joe Apr 25 '12 at 16:58
1  
let us continue this discussion in chat –  Kikaimaru Apr 25 '12 at 17:07
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.