Search code examples
xmlxna-4.0xml-deserializationcontent-pipeline

XNA using content.load XML always returns the same object?


I'm trying to use an xml file for spritesheet data; I have a frame class that either holds a rectangle or another list of frames (it can be a frame itself, or a holder for more frames). The xml holds all rectangles for the frames. I've added the xml to the content project and use Content.load("xmlname") to load it.

This all works perfectly fine when using it once. But when I create 2 objects that share the same spritesheet (and thus the same xml data fle) they dissapear when these 2 objects are on the same frame. After a lot of frustration I figured out that the xml file always returns the same object, thus shares frames so it can only draw the frame one place at a time.

Here's a short part of the xml file:

<?xml version="1.0" encoding="utf-8"?>

<rect>0 0 0 0</rect>

<frames>

  <Item>
    <rect>0 0 0 0</rect>
    <frames>

      <Item>
        <rect>19 27 15 22</rect>
        <frames></frames>
        <label>DOWN</label>
      </Item>

      <Item>
        <rect>2 27 15 23</rect>
        <frames></frames>
        <label>DOWN</label>
      </Item>

      <Item>
        <rect>19 27 15 22</rect>
        <frames></frames>
        <label>DOWN</label>
      </Item>

      <Item>
        <rect>36 27 15 23</rect>
        <frames></frames>
        <label>DOWN</label>
      </Item>

    </frames>
    <label>DOWN</label>
  </Item>

Stripped down version of the class:

    public class Frame
{
    public Rectangle rect; //means this is an image

    private Renderable renderable = null;

    private List<Frame> frames;

    private Texture2D texture;
    private int currentFrame = 0;

example usage:

    Sprite sprite1 = new Sprite();
    sprite1.frame = Content.load<Frame>("xml");
    sprite1.frame.getFrame(0).alpha = 0.5f; 

    Sprite sprite1 = new Sprite();
    sprite2.frame = Content.load<Frame>("xml"); //<--- doesn't return a new object, returns the same object as sprite 1 uses
     //frame  0 in sprite 2 has an alpha of 0.5 aswell, without having modified it

I tried to manually deserialize the xml, but deserializing lists is a nightmare. Am I doing something wrong here? Seems so strange that it returns the same object


Solution

  • This is by design. In most situations you only want to load an asset once, and then reuse it. Loading it multiple times would be a waste of time and memory.

    Ideally any assets you load from disk should be immutable objects, so you should change your design so you don't need to modify their fields.

    But sometimes that's not possible. The next best solution would be to implement ICloneable on the class you want to make multiple copies of.

    The harder-to-implement-correctly and kind of ugly alternative would be to inherit from ContentManager and override its methods such that it loads the asset each time, as described in this blog post.