Author Topic: How are you handling Serialization with Unity3D?  (Read 27788 times)

Offline RogueDeus

  • Newbie Mark III
  • *
  • Posts: 47
Re: How are you handling Serialization with Unity3D?
« Reply #15 on: September 29, 2011, 01:33:41 pm »
You know, the more I look at these short cuts (like Enums and Delegates) the more I realize why code is getting bigger and slower... Its faster (easier) to write, but takes longer to process. I suppose that is the trade off really. Otherwise we would still be writing in machine code! :p

Enums add no extra processing whatsoever if you use them right.  They are just like CONSTs.

Maybe I am misunderstanding this then?

http://stackoverflow.com/questions/105372/c-how-to-enumerate-an-enum

In the comments on the answer there is this:
Quote
52    
   
Enumerating an enum with 52 values 100000 times: 3884ms Enumerating an int[] with 52 values 100000 times: 99ms yes, far slower than an array - but still fast unless you have 51 million enum values ;) – TheSoftwareJedi Oct 15 '08 at 1:41

If I understand this correctly, he is saying that a foreach loop using a list of Enums is slower then using an array. Not exactly game breakingly slow, just slower.
"It is impossible for a man to learn what he thinks he already knows." - Epictetus

Offline RogueDeus

  • Newbie Mark III
  • *
  • Posts: 47
Re: How are you handling Serialization with Unity3D?
« Reply #16 on: September 29, 2011, 02:18:06 pm »
I apologize if I am being argumentative. Just trying to make sure I understand which is correct.

If there is no performance hit with liberal use of Enums then I will use them as often as I can. But if there is, I will use them only when a more complex solution is less agreeable.
"It is impossible for a man to learn what he thinks he already knows." - Epictetus

Offline x4000

  • Chris McElligott Park, Arcen Founder and Lead Dev
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 31,651
Re: How are you handling Serialization with Unity3D?
« Reply #17 on: September 29, 2011, 02:28:20 pm »
You've have to check the specs, and which version of .NET is in question, and so on.  But unless there's a lot of boxing/unboxing going on, there should be no reason.

And actually: with a foreach loop, which is horribly inefficient to begin with, there would be boxing.  So I'm not surprised at that.  But that's a problem with foreach, not with using an enum.  Use for, while, and do while -- never use foreach.
Have ideas or bug reports for one of our games?  Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline RogueDeus

  • Newbie Mark III
  • *
  • Posts: 47
Re: How are you handling Serialization with Unity3D?
« Reply #18 on: September 29, 2011, 02:30:13 pm »
You've have to check the specs, and which version of .NET is in question, and so on.  But unless there's a lot of boxing/unboxing going on, there should be no reason.

And actually: with a foreach loop, which is horribly inefficient to begin with, there would be boxing.  So I'm not surprised at that.  But that's a problem with foreach, not with using an enum.  Use for, while, and do while -- never use foreach.

Thanks I will remember that!
"It is impossible for a man to learn what he thinks he already knows." - Epictetus

Offline Hearteater

  • Core Member
  • *****
  • Posts: 2,334
Re: How are you handling Serialization with Unity3D?
« Reply #19 on: September 29, 2011, 02:31:48 pm »
I'd like to point out is that the comment you quoted RogueDeus is almost 3 years old.  It may not be reflective of C#'s current performance.

For what it is worth, my general rule is to get clean, maintainable code working and come back with a better solution later if that turns out to be your bottleneck.  Chances are you'll have a better understanding of how to do good optimizations later anyway.

Offline RogueDeus

  • Newbie Mark III
  • *
  • Posts: 47
Re: How are you handling Serialization with Unity3D?
« Reply #20 on: September 29, 2011, 02:35:19 pm »
I'd like to point out is that the comment you quoted RogueDeus is almost 3 years old.  It may not be reflective of C#'s current performance.

For what it is worth, my general rule is to get clean, maintainable code working and come back with a better solution later if that turns out to be your bottleneck.  Chances are you'll have a better understanding of how to do good optimizations later anyway.

Good point. I often forget to check that... It is so easy to get overloaded with info on that site that I only grab the gist of something before moving to the next most relevant tidbit.
« Last Edit: September 29, 2011, 05:55:13 pm by RogueDeus »
"It is impossible for a man to learn what he thinks he already knows." - Epictetus

Offline RogueDeus

  • Newbie Mark III
  • *
  • Posts: 47
Re: How are you handling Serialization with Unity3D?
« Reply #21 on: September 30, 2011, 04:23:20 pm »
I am paying around with Dictionaries to create a local variable system so I can store/retrieve data on objects that have the script component available, and I was wondering about anyone's thoughts on its feasibility.

Essentially, when run, the script creates up to four Dictionaries Int, Float, String, and Object types, with string Keys. (I may change that to an enum). This is primarily to save serializable data for that whole (data, manipulator, projector) thing I talked about.

I tried using the dictionaries via a generic methods but must be doing something wrong, so I created specific methods for each. (Clipped the extra get/set's to shorten it)

Code: [Select]
public class LocalVariables : MonoBehaviour
{
private Dictionary<string, int> localIntDictionary;
private Dictionary<string, float> localFloatDictionary;
private Dictionary<string, string> localStringDictionary;
private Dictionary<string, object> localObjectDictionary;

[HideInInspector]
public bool disableLocalIntegers, disableLocalFloats, disableLocalStrings, disableLocalObjects;




// Use this for initialization
void Start ()
{
if(!disableLocalIntegers)
{
localIntDictionary = new Dictionary<string, int>();
}
if(!disableLocalFloats)
{
localFloatDictionary = new Dictionary<string, float>();
}
if(!disableLocalStrings)
{
localStringDictionary = new Dictionary<string, string>();
}
if(!disableLocalObjects)
{
localObjectDictionary = new Dictionary<string, object>();
}
}

void Update()
{

}


#region Base Getters/Setters
private void NoDictionary(string dictionary, string varName)
{
Debug.LogError(gameObject.name + " - Has no " + dictionary
+ " dictionary!! To save/get: " + varName);
Debug.Break(); //Stop the game.
}

public int GetLocalInt(string varName)
{
if(disableLocalIntegers || localIntDictionary == null)
NoDictionary("Local Integer", varName);

return localIntDictionary[varName];
}

public void SetLocalInt(string varName, int value)
{
if(disableLocalIntegers || localIntDictionary == null)
NoDictionary("Local Integer", varName);

localIntDictionary.Add(varName, value);
}

public float GetLocalFloat(string varName)
{
if(disableLocalFloats || localFloatDictionary == null)
NoDictionary("Local Float", varName);

return localFloatDictionary[varName];
}

public void SetLocalFloat(string varName, float value)
{
if(disableLocalFloats || localFloatDictionary == null)
NoDictionary("Local Float", varName);

localFloatDictionary.Add(varName, value);
}

public string GetLocalString(string varName)
{
if(disableLocalStrings || localStringDictionary == null)
NoDictionary("Local String", varName);

return localStringDictionary[varName];
}

public void SetLocalString(string varName, string value)
{
if(disableLocalStrings || localStringDictionary == null)
NoDictionary("Local String", varName);

localStringDictionary.Add(varName, value);
}

public object GetLocalObject(string varName)
{
if(disableLocalObjects || localObjectDictionary == null)
NoDictionary("Local Object", varName);

return localObjectDictionary[varName];
}

public void SetLocalObject(string varName, object obj)
{
if(disableLocalObjects || localObjectDictionary == null)
NoDictionary("Local Object", varName);

localObjectDictionary.Add(varName, obj);
}
#endregion

}

I think I will remove the MonoBehaviour and use it as a lib class and not a script component.
« Last Edit: September 30, 2011, 04:25:16 pm by RogueDeus »
"It is impossible for a man to learn what he thinks he already knows." - Epictetus

Offline x4000

  • Chris McElligott Park, Arcen Founder and Lead Dev
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 31,651
Re: How are you handling Serialization with Unity3D?
« Reply #22 on: September 30, 2011, 04:27:38 pm »
I think you're over-generalizing.  Also, indexing by strings is incredibly slower than by enums.  String comparisons are wicked slower than enum comparisons, and the comparison time varies by the length of the string.


You don't need some fancy data structure to store data in so that you can later serialize it.  All you need is just regular variables.  Then when it comes time to serialize, your serialization code needs to automatically write those variables.  Look at how microsoft ISerializable classes tend to look.  You don't have to use their serialization method (in fact I recommend not), but their general structure is fine.  What you've got in the code you posted is just going to add slowdown and memory bloat -- take out the middle man.
Have ideas or bug reports for one of our games?  Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline RogueDeus

  • Newbie Mark III
  • *
  • Posts: 47
Re: How are you handling Serialization with Unity3D?
« Reply #23 on: September 30, 2011, 05:42:42 pm »
I think you're over-generalizing.  Also, indexing by strings is incredibly slower than by enums.  String comparisons are wicked slower than enum comparisons, and the comparison time varies by the length of the string.

Thanks, I had not considered searching for speed deference in key types.

You don't need some fancy data structure to store data in so that you can later serialize it.  All you need is just regular variables.  Then when it comes time to serialize, your serialization code needs to automatically write those variables.  Look at how microsoft ISerializable classes tend to look.  You don't have to use their serialization method (in fact I recommend not), but their general structure is fine.  What you've got in the code you posted is just going to add slowdown and memory bloat -- take out the middle man.

My thinking behind this is to have the option of creating the local variable storage in case I wanted to quickly add a repository of data somewhere for some reason. Say, for custom scripting later on. My inexperience in large projects means that I am pretty clueless as to what I need to have ready for later, so having a general place I can store and retrieve data when I want might help me speed up the prototyping as well. Of course, hard data would be turned into regular class variables once ironed out.

I am still kind of getting used to using collection type functions. All my previous scripting experience was absent these data structures (even arrays). Thus I had to concoct very elaborate ways of storing and retrieving data...  Now that I have free reign to use them I am sure I will get a bit carried away until experience tempers my lusts. :p
"It is impossible for a man to learn what he thinks he already knows." - Epictetus

Offline x4000

  • Chris McElligott Park, Arcen Founder and Lead Dev
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 31,651
Re: How are you handling Serialization with Unity3D?
« Reply #24 on: September 30, 2011, 06:28:24 pm »
Fair enough, there's more than one way to do stuff.  My experience is that the less code you can write to do something, the better, though -- especially in the long term.  "What is the briefest, most concise, least-operations-using way I can write this?" is always my question to myself.  But Keith and I are performance tuning addicts.
Have ideas or bug reports for one of our games?  Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline RogueDeus

  • Newbie Mark III
  • *
  • Posts: 47
Re: How are you handling Serialization with Unity3D?
« Reply #25 on: September 30, 2011, 06:33:30 pm »
Fair enough, there's more than one way to do stuff.  My experience is that the less code you can write to do something, the better, though -- especially in the long term.  "What is the briefest, most concise, least-operations-using way I can write this?" is always my question to myself.  But Keith and I are performance tuning addicts.

I am sure I will be too once I get a better idea how to make things work the way I want. :)

Though I don't want to give the impression that I will be stuffing local variable banks on every object in the game or anything. Just that I like having options available in case I find a need.

Please keep critiquing me, I need to keep myself thinking. And the best way I have found to do that is my engaging others.  :)
"It is impossible for a man to learn what he thinks he already knows." - Epictetus

Offline RogueDeus

  • Newbie Mark III
  • *
  • Posts: 47
Re: How are you handling Serialization with Unity3D?
« Reply #26 on: October 02, 2011, 11:32:32 pm »
Pardon me if this is a bit too academic but I want to make sure that I am not confusing anything in regards to the big picture of serialization as it relates to developing saved games.

Essentially when a game has the option of saved game starts, it has two movements that end in a running game.

Movement #1: Starts a game from scratch. The game program begins to run and fills the spaces with new data.

Movement #2: Starts a game from saved data. Some, usually not all, of the program is filled with retrieved data, the rest with new data.

Thus, when you write the program you are writing two start-up processes that end in the same playable state, the difference is where the data originates.

Most games serialize the savable game data  when the ‘Save Game’ button is pushed. While others serialize the data as the game is played. Either way accomplishes the same goal (saving data for later) but only the ‘as played’ version allows for more complex game play scenarios where the world can be effectively endless, as its saved and restored as needed.

I can only guess that the push button & save game version is less prone to corruption? But also more prone to lost game time as if you forget to push ‘save’ you lose the time since the last one.

Keeping this in mind, the developer must decide which is more reasonable to implement. Or even necessary.

Am I mistaking something?
"It is impossible for a man to learn what he thinks he already knows." - Epictetus

Offline x4000

  • Chris McElligott Park, Arcen Founder and Lead Dev
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 31,651
Re: How are you handling Serialization with Unity3D?
« Reply #27 on: October 02, 2011, 11:38:16 pm »
There is no game that saves all the data as-played in the sense you seem to mean.  Data isn't just streamed to disk or anything.  Regardless of whether a button is pushed or a timer is tripped inside the game program, and regardless of whether or not the entire game state is saved or only art of it... a function moves some data to disk, that can later be read back.  That's it.

In terms of starting a new game or loading a savegame, the difference there should be minimal.  The amount of code for starting a new game or loading a savegame are both trivial compared to the amount of code for actually running the game, which is the same in either case.  It's like walking in your front door or your back door; yes, both are different -- this is obvious, but you get into your same house either way.  And those doors are just a very tiny part of the complexity of your whole house.
Have ideas or bug reports for one of our games?  Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline RogueDeus

  • Newbie Mark III
  • *
  • Posts: 47
Re: How are you handling Serialization with Unity3D?
« Reply #28 on: October 03, 2011, 12:10:15 am »
There is no game that saves all the data as-played in the sense you seem to mean.  Data isn't just streamed to disk or anything.  Regardless of whether a button is pushed or a timer is tripped inside the game program, and regardless of whether or not the entire game state is saved or only art of it... a function moves some data to disk, that can later be read back.  That's it.

I seem to have said something wrong.

I did not mean to imply that any game state is ever fully saved, or fully streamed. Only that the data to be saved (for whatever reason) is traditionally done in a single step (such as pushing 'Save Game') or in an 'as played' step where it occurs almost immediately after savable data is available.


In terms of starting a new game or loading a savegame, the difference there should be minimal.  The amount of code for starting a new game or loading a savegame are both trivial compared to the amount of code for actually running the game, which is the same in either case.  It's like walking in your front door or your back door; yes, both are different -- this is obvious, but you get into your same house either way.  And those doors are just a very tiny part of the complexity of your whole house.

Again, I seem to have said something wrong as that is essentially what I was trying to say.

Just to reiterate for the sake of clarity…

When the game starts the relevant data is either retrieved (from a serialized location), or created (from new processes), based on whether or not it’s a saved game that’s starting, or a new game. Even if that data is nothing more than the player name and location, a saved game places them where they last exited the game and a new game places them where all new game players start… In the end, it is the same game that is running.

In more complex scenarios the developer must consider if any serializable data is relevant upon any player action.

Such that, entering a room will always check for the serializable variable that says if it’s been entered or not already. A new games flag is unset, where the saved games flag is. The question becomes when that flag is to be serialized.

Did I explain that clearer?

Note: I sometimes tend to get a bit esoteric when talking about things I am new too and I apologize if I complicate these conversations as a result. I am sure that once I get more familiar with the normal programming parlance it wont be as much of a head ache to deal with my questions...  :-[
"It is impossible for a man to learn what he thinks he already knows." - Epictetus

Offline x4000

  • Chris McElligott Park, Arcen Founder and Lead Dev
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 31,651
Re: How are you handling Serialization with Unity3D?
« Reply #29 on: October 03, 2011, 09:33:41 am »
Fair enough.
Have ideas or bug reports for one of our games?  Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!