Hi I’m working on a game and I need to save data such as weapons. Right now I have a Database class that loads and saves everything using XML Serializer. I’m not Shure this is the best way of doing this. I’m targeting mobile devices and This could be slow(Have no devices to test right now) since this requires using both reflection and copying everything to a Dictionary. Would it be better if I manually read the XML using XML Writer and Reader, or maybe have a prefab that already holds all the data(Seems sloppy).
What’s the best practice for going about doing something like this?
Database Class(Only save and load classes to make code shorter for readers)
public class Database
{
public static Database i;
public Dictionary<string,Class> classes = new Dictionary<string, Class>();
public Database()
{
i = this;
Load ();
}
public void Load()
{
LoadClasses ();
}
public void LoadClasses()
{
Class[] _classes;
XmlSerializer ser = new XmlSerializer(typeof(Class[]));
using (XmlReader reader = XmlReader.Create("Assets/Resources/Data/Classes.xml"))
_classes = (Class[]) ser.Deserialize(reader);
for (int i = 0; i < _classes.Length; ++i)
classes.Add(_classes[i].id,_classes[i]);
}
public void SaveClasses()
{
Class[] _classes = new Class[classes.Count];
classes.Values.CopyTo (_classes, 0);
XmlSerializer serializer = new XmlSerializer(typeof(Class[]));
using (TextWriter writer = new StreamWriter("Assets/Resources/Data/Classes.xml"))
serializer.Serialize(writer,_classes);
}
}
Example Class
public class Weapon : Item
{
public int rank = 0;
public int mt = 0;
public int hit = 0;
public int crt = 0;
public int minRng = 0;
public int maxRng = 0;
public int wt = 0;
public int wEx = 0;
public enum WeaponAttackType { PHYSICAL, MAGICAL };
public WeaponAttackType weaponAttackTypeClose;
public WeaponAttackType weaponAttackTypeRanged;
public Weapon()
{
}
public Weapon(string id)
{
this.id = id;
itemType = ItemType.WEAPON;
weaponAttackTypeClose = WeaponAttackType.PHYSICAL;
weaponAttackTypeRanged = WeaponAttackType.PHYSICAL;
}
public static Weapon CreateCopy(Weapon toCopy)
{
Weapon copy = new Weapon(toCopy.id);
copy.name = toCopy.name;
copy.description = toCopy.description;
copy.uses = toCopy.uses;
copy.uses = toCopy.uses;
copy.currentUses = toCopy.currentUses;
copy.worth = toCopy.worth;
copy.icon = toCopy.icon;
copy.mesh = toCopy.mesh;
copy.texture = toCopy.texture;
copy.itemBehaviour = toCopy.itemBehaviour;
copy.itemType = toCopy.itemType;
copy.rank = toCopy.rank;
copy.mt = toCopy.mt;
copy.hit = toCopy.hit;
copy.crt = toCopy.crt;
copy.minRng = toCopy.minRng;
copy.maxRng = toCopy.maxRng;
copy.wt = toCopy.wt;
copy.wEx = toCopy.wEx;
copy.weaponAttackTypeClose = toCopy.weaponAttackTypeClose;
copy.weaponAttackTypeRanged = toCopy.weaponAttackTypeRanged;
return copy;
}
}
First, technically not a ‘database’. More like a save state.
Anything that can be serialized, implement some ISaveStateSerializable interface. There should be two functions on it, a ‘Serialize’ and ‘Deserialize’ methods (name that whatever you want… ‘save/load’, whatever). The function should receive a serialized data writer/reader object that implements converting the information it receives from the object being serialized into xml.
Nice thing is the writer/reader object can inherit from some base class (or implement an interface). And you can have different reader/writers that support different serialization techniques. This way if you go an benchmark some data storage method that turns out to be to slow, you just change out the writer/reader object that does something else. You could actually read and write to a REAL database with one of your serialization techniques.
I’ve been using the ScriptableObject technique for making databases these past few weeks and I’m actually enjoying it a lot. Unfortunately, I got caught up in a bit of a twisted complication on the backend of my editor scripts (my attribute database has to have constant access to my item database, and vice-versa) which is screwing up the portability of the solution, or else I would share it. The “Inventory Master” asset on the AssetStore is actually a really good example of this approach though, if you want to check it out.
XML is driven by the same principle as a database. A database can be a any thing, its a backed solution that stores and read data. XML does this, but is not really secure, for a mobile game your code is fine.
A database can be driven by xml. Doesn’t necessarily make all xml a database.
Of course technically, yes, you can refer to what OP wants as a database. But traditionally it’s not what one would expect when discussing the topic of databases.
Seeing as my database background is in primarily nosql systems such a D3, no, not mixing them up with SQL.
Don’t feel like having another pedantic semantics argument with you Ironmax.
I’ll just repeat what I said… “A database can be driven by xml. Doesn’t necessarily make all xml a database.”. Meaning XML can be used to make a databsae, but it is not inherently a database.
You even mirror this sentiment when you say: “XML have been used for database solution many times.” as well as “So technically xml solution CAN be used as a database”.
Performance shouldn’t be a big issue if you are careful about when you are loading and saving data. Of course it depends on the amount of data you are deserialize, but ints, floats a bit of text shouldnt be an issue.
Although, make sure you tell the user that loading is occurring and they wont mistake it for poor performance.
Have everything you need loaded, loaded, before the big battle starts!
You are not the only one who was confused. There are not many people on my ignore list, but I get caught out from time to time when someone engages them in conversation.
Testing on target devices is important. You can waste a lot of time optimising for things that you don’t need.
Putting a layer of abstraction between your game and your data storage is a great idea. This lets you delay dealing with the problem until you can test and benchmark.
Thanks for all the helpful replies. I should clarify that I am only loading everything once at the start up of the game and I’m only storing ints,strings and floats. I’m installing Visual Studio 2013 with Phone SDK to test on my phone. At the moment I don’t have mobile devices for android or iOS but the Windows phone should work for now since its a low end one when it came out and a few years old. I’m also considering maybe running Load in a Thread and that should Help. Only issue with this is that Windows Phone SDK does not support threading, unless I use the Windows Store Export(Which works for phone) and not the phone one but that runs slower on my phone from previous testing of another game.
Here is an example of all my classes being saved to XML File. I agree with Ironmax, I would consider this a Database since its a file that holds a array of data. Just because its local does not make it a Database. There is 500(Only few in example) in there. I should have no way near 500 of total classes, items, and units so if this loads fast I should be good.
I will test after Work and Visual studio is done installing.
Lysander that’s a different way of going about it, I have never used scriptable objects before. Ill check out that asset to see if I can learn anything and plus its nice seeing other peoples work.
Lordofduct your idea is a good one and will consider it. When I program my two goals are stupid simple and optimization.
Love your profile picture BoredMormon and thanks for your opinion.
Looks good, it would still be a database even its local Some dev even use BLOB local as database. I never had any issue with xml as backend database, its good for mobile/small projects. What i think Lordofduct is trying to say is that a more typical database standard as SQL would be better with other projects where speed would be important and your data becomes large… You can sync your Data more than just ones when you load the game, every time you change scene or or any other big events happens in your game. Visual Studio is a good recommendation you can make Unity work with VS as standard editor instead of Mono.
Good luck
Not Shure what the real load time is but it was all done within the time Unity’s splash screen witch lasted around 5 seconds. There was a total of 1000 classes to load so that’s good. I actually only using two scenes in the project, one Scene is for the entire game and the other one contains some extra scripts for editors. I just have one Mono behavior Class(For the game Scene) that’s called Game and its attached to the only object in game called main. Every other class is a regular C# class. This might be weird but that’s how I roll most of the time when working with Unity. As for Visual Studio its my favorite IDE but I installed Windows 10 and I was to lazy to reinstall it lol. Anyway I’m happy with the speed. Again thanks for all your replies.