0

I am hitting a strange issue with score serialization in my game.

I have a LevelHighScore class:

[System.Serializable]
public class LevelHighScores
{
    readonly Dictionary<Level, ModeScores> scores;
    // clipped out the rest for simplicity
}

With a enum key, Level.

I recently added some new levels to my game, but instead of adding the new levels to the end of the enum, I added the new enums in alphabetical order. Now when I load the game my new levels have existing scores associated with them, making me think that the ordinal of the enums are having an effect on the serialization / deserialization.

I want to avoid to avoid this issue when adding levels in the future. I also don't want to have to remember to only add levels to the end of the enum.

Is there a way to ensure that enum are deserialized consistently, even when retroactively adding new values?

James McMahon
  • 48,506
  • 64
  • 207
  • 283
  • Using a `Dictionary` instead of a level keyed dictionary seems like it would be an effective work around. Though it loses the type safety of an enum. Would love to hear other suggestions. – James McMahon Jul 03 '16 at 03:06
  • 1
    You could assign your enum values explicitly so the order doesn't matter. See https://stackoverflow.com/questions/1681285/pros-and-cons-explicitly-setting-enum-fields-values – dbc Jul 03 '16 at 07:01
  • @dbc, That's a good suggestion, you should expand that into an answer – James McMahon Jul 03 '16 at 14:45

2 Answers2

1

Add the [DataContract] attribute to the enum and serialize using the DataContractSerializer. Place an [EnumMember] attribute on individual values.

That will cause the value to be serialized by name, not by numeric value.

To be sure I'd test serializing to a file (or a string if it's XML serialization) and see what it's storing to be sure that it works, and to be sure it's not already serializing by the name. Otherwise you won't know for sure if that's the cause.

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
  • [Looking into this further](https://msdn.microsoft.com/en-us/library/aa347875(v=vs.85).aspx), this looks like a good solution. Unfortunately, Unity doesn't have have support for DataContracts by default. It looks like you can import the System.Runtime.Serialization.dll to add it, but I'm not sure that's the best solution for my particular project. – James McMahon Jul 03 '16 at 04:19
0

I ended up following dbc's suggestion and adding explicit values to the enum.

So, I changed Level from,

public enum Level
{
    Aquarium,
    Crescendo,
    HungarianDance,
    MapleLeafRag,
}

To

// NOTE: the numbers here don't represent order,
// they are just to ensure proper serialization
public enum Level
{
    AmazingPlan = 4, // new level
    Aquarium = 0,
    Crescendo = 1,
    HungarianDance = 2,
    MapleLeafRag = 3,
}

This was a nice simple solution to my problem, though I think for non-Unity projects Scott Hannen's answer is probably the way to go.

Community
  • 1
  • 1
James McMahon
  • 48,506
  • 64
  • 207
  • 283