XNA Creators Club Online
Page 1 of 1 (8 items)
Sort Posts: Previous Next

ContentSerializer attribute and design question

Last post 1/22/2010 2:51 PM by Jim Perry. 7 replies.
  • 11/19/2009 3:52 PM

    ContentSerializer attribute and design question

    I am currently working on my grid for a 3D tactical RPG and am trying to make sure everything is good for a future level editor. While I have a solution that works, I think I can make it better (while learning more about XNA) and wanted to run my design idea here first.

    The main design is broken into four classes:

    The first class is the grid square that the game will use. It has a Texture, Effect, VertexBuffer, etc. like the Model class but also other game-related properties.

    The second class extends from the first grid square class and adds in extra fluff stuff that the level editor will use.

    The third class is a Content match for the first grid square class, using TextureContent and things to serialize correctly.

    The fourth class is a custom content processor that will take in the second fluff grid square and output the Content grid square that can be serialized.

    The process should flow as such:

    - Level editor creates fluff grid squares and saves it to XML with the IntermediateSerializer
    - Custom processor takes in the fluff grid squares and uses them to load the correct textures and set the vertices in the content objects so they can be serialized
    - Game loads the serialized objects into the basic grid square

    So first off, does this seem like a good approach?

    My main concern is this: How will the ContentSerializerIgnore attribute work when deserializing the objects at run-time? I plan on ignoring the Texture/VertexBuffer/BasicEffect classes so that when the level editor outputs the XML file it will not attempt to write those (since it can't), but will doing this make it so that those classes aren't populated with the correct information when deserialized? Am I stuck with custom writers/readers in this situation or can I still leverage automatic serialization?

    Thanks in advance.
    --Kainsin
  • 11/19/2009 3:58 PM In reply to

    Re: ContentSerializer attribute and design question

    ContentSerializerIgnore does what it says: it ignores it when serializing, and since it won't exist when deserializing, it ignores it when deserializing.

    This can be a problem for assets like Effects, Textures, VertexBuffers, etc...

    What I did was create a service called ContentProvider which wraps the content manager.  When an asset is loaded, I add the asset and its full name to a dictionary so I can reverse map it later.  I use a type converter, which can get access to my singleton game class, and convert the asset to and from string using the reverse mapping dictionary.  This way things like Effect can be serialized to and from string, the string being the name of the asset.  Haven't tried this with ContentSerializer yet, but hopefully it will work.

    If not, I have another easier technique to implement.  Let's say you have a class with a Texture named MyTex.  Put a ContentSerializerIgnore attribute on that property, create another property named MyTextName as a String.  Use MyTextName to load / unload the asset, and serialize this value so you know what texture to load when your class is deserialized.
  • 11/19/2009 4:06 PM In reply to

    Re: ContentSerializer attribute and design question

    Yes, the texture name as a string and loading it after deserialization is what I am currently doing now and it does work.

    As I've been exposing myself to more of the XNA framework I was wondering if I might be able to leverage a custom content processor to remove this step. While the Texture/Effect/VertexBuffer fields will be marked with the ContentSerializerIgnore attribute, their respective TextureContent/etc fields in my grid square content class will not. This means they should be serialized correctly, but what happens when they are deserialized?
    --Kainsin
  • 11/19/2009 5:58 PM In reply to

    Re: ContentSerializer attribute and design question

    Basically, the serializer will serialize the asset name property as a string, and when deserializing it will set the asset name property as string.  You could do something like this:

    public String MyTextName
    {
    get{ return myTextName;}
    set{ myTextName = value; myTex = LoadTexture(myTexName); }
    }

    Texture LoadTexture(String assetName)
    {
    // load it here somehow
    }

    And when the content serializer sets that property, it will load the asset.
  • 11/19/2009 6:04 PM In reply to

    Re: ContentSerializer attribute and design question

    Thank you for the reply but as I already mentioned, that technique is pretty much what I am already doing now.

    My question is about serializing a GridSquareContent class with *Content fields that have not been marked with any attribute, and then deserializing it into a GridSquare object with the corresponding run-time types that have been marked with the ContentSerializerIgnore attribute.
    --Kainsin
  • 11/26/2009 4:27 PM In reply to

    Re: ContentSerializer attribute and design question

    Answer
    Reply Quote
    After messing around with things for the past week or so I finally came up with a solution I like. It seems as though having the ContentSerializerIgnore attribute on a field will prevent it from being deserialized, so my original idea is not workable. Instead I went with a 3 part solution:

    1. Grid types that can recalculate their vertices, used for both the level editor and game
    2. Intermediate types that just hold onto the data that can not be recalculated on the fly
    3. Content types that can take the intermediate types and construct content types (MaterialContent, VertexBufferContent, etc)

    My process goes as such:

    1. Level editor uses the basic types to form the grid and when the user wants to save, it pulls out the required data into intermediate types and saves it as an XML file.
    2. Custom processor takes the intermediate types loaded from the XML importer and outputs the required content types
    3. Game loads the basic grid types as normal

    This has the benefit that the grid is still mutable while playing, so I can adjust the height of squares or deform it if needed.

    Loading the grid data also fell from ~9 seconds to less than 1 second which is always nice. :)

    While I know this might be fairly easy for some people, I thought I'd share my final answer for anyone that was interested. I have a good amount of programming experience, but this is my first time getting this involved with game development.

    --Kainsin
  • 1/22/2010 12:59 PM In reply to

    Re: ContentSerializer attribute and design question

    Hey first off sorry to bump such an old topic, but I've been trying to do what you've described here. I'm not sure how to load a texture inside my custom object. The big problem is I don't know how to do the

    //load it here somehow

    part of your example.

    I think I need access to the Content variable which is part of my Game1 class, but how do I get access to it?
  • 1/22/2010 2:51 PM In reply to

    Re: ContentSerializer attribute and design question

    Pass a reference to the ContentManager to the object? Use a singleton to either the ContentManager or the Game? Make the ContentManager static? There's a lot of possible solutions.
    Jim Perry - Microsoft XNA MVP
    If people spent a minute searching the forums and reading the FAQs before posting I'd be out of a job.
      Got some XNA Game Studio/XNA Framework development info to share with the community? Put it on the XNA Wiki.
        Please mark posts as Answers or Good Feedback when appropriate.
Page 1 of 1 (8 items) Previous Next