Unity Web Player, Cookies, and saving player data...

Hello everyone,

I was hoping you fine folks could help me out a bit. I am trying to find a reliable way to store (persistant)user date while using the Unity Web Player. I know a little about Player Prefs but that doesn't seem to be a good solution to storing a lot of data. I basically want to store things like the levels the player has unlocked as well as weapons and other unlockable stuff.

I was thinking about saving files to the local machine(can apparently be done with some javascript wizadry), or maybe using cookies, though I'm not even sure how cookies work.

Has anyone done something similar that could give me some advice or point me to some good articles I can read?

Thanks and happy new year! :D

Comments

  • Ok, what exactly do you need to do?

    Are you looking to store session-type data, like progress in a game that players are going to restart often (think of an arcade shmup, for instance) or are you wanting to store longer-term data that players will be annoyed about losing?

    I mainly ask because cookies and player prefs (which both let you store similar amounts of data, nothing too huge) tend to be relatively transitory, so I wouldn't rely on those if you had important player progress to store. The most reliable storage is always going to be in your own server-side database, provided you've got a website to keep that on. Unity's built-in web queries are pretty solid, we use those for all DD's data passing between our server and the individual clients.

    For DD we store player profiles, savegames and debug info (crash messages, event data) in a couple of databases on our main server. We use player prefs to store the username that a player last logged in with ;) (Always always always use good password security practices if you're asking players to log in, it's not difficult and will save you time later, trust me)

    I would imagine that the cookie route would require the Unity plugin talking to some custom Javascript you've got waiting on the webpage that's serving the game. So that's probably going to be a related hassle.
  • @dislekcia, thanks for the response. The things I want to do is actually for that space shmup I posted here a while back. Wanted to work on it some more because I'm still not happy with how it turned out. So session-type data, yes.

    I want to store the weapons/upgrades that the players purchase in game, so it's not really anything complex. Just a lot of bits to set to 1 or 0. I'm also trying to get away with something I don't have to pay for, which excludes the server side DB. :/

    Working with player prefs for lots of different choices felt really clunky to me. I don't know if I was just messing up, but it doesn't seem to be designed to store a lot of information. Rather specific things the user last used...like the the last username.

    I read up some more about cookies and I'm afraid of using them because it seems that they have a limited time to live. Which is not ideal.

    So all in all it seems like I'm pretty screwed :P I either need some clever way to encode my data so I can use the player preferences to better effect, or I need to fork out the cash for some server side functionality. :D
  • Why not smack all your on/off bits into a single string and save that in Player Prefs? That shouldn't be too hard, right?
  • @Rigormortis why not save all that data as one specially formatted string that you save to PlayerPrefs and decode that at runtime in the game? Like W1452L6 to show they've unlocked weapons 1, 4, 5, 6 and 2 and have reached level 6. Also, not neccessarily related but you should check out dreamlo for high scores and Lumos for player metrics
  • edited
    Yes, I can also recommend the single string method.

    What we do is keep our save-data in a Serializable class (the fields are variables containing Serializable instances of the various different things we save, PlayerSaveData, List<MonsterSaveData>, etc.), we serialise the entire thing to an XML string, and dump it in PlayerPrefs. For about 500 KB - 2 MB there is a split-second stutter on iPhone, and none on PC / web (on my machine).

    There are quite a few arguments against XML... all I can say is it worked well for us.

    One caveat: it has happened to me three times (on different projects) that an error is reported that make me think that List<T> is (suddenly) not serializable (and every time I only remember it once we found the problem). In each case it was a variable in T that was not serializable (sometimes a variable in a variable...).

    Another one: dictionaries are not serializable. I usually convert a dictionary to two coupled Lists for saving.


    using System.IO;
    using System.Xml;
    using System.Xml.Serialization;
    
    public class Serializer
    {
    	public static string SerializeObject<T>(T obj)
    	{ 	
    		XmlSerializer xmlSerializer = new XmlSerializer(typeof(T)); 
    		StringWriter stringWriter = new StringWriter();
    		XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter);
    		xmlSerializer.Serialize(xmlWriter, obj);		
    		string xml = stringWriter.ToString();
    		
    		xmlWriter.Close();
    		stringWriter.Close();
    		
    		return xml;		
    	}
    
    	public static T DeserializeObject<T>(string xml)
    	{ 
    		XmlSerializer serializer = new XmlSerializer(typeof(T));        
    		StringReader stringReader = new StringReader(xml);        
    		XmlTextReader xmlReader = new XmlTextReader(stringReader);        
    		T obj = (T)serializer.Deserialize(xmlReader);
    		
    		xmlReader.Close();
    		stringReader.Close();
    		
    		return obj;
    	}
    }
  • @dislekcia,@Stray_Train, That was what I was working towards last time. It still has the problem of the data being a bit transient but I guess I'll have to make that sacrifice.

    @hermantulleken, is the XmlSerlializer something built into unity? I read somewhere, that the built in xml parser usually adds about 5MB to the file size. I was wondering if this was your experience as well?

    Thanks for the responses guys. I Appreciate it. :)
  • I've used XmlSerializer before, it's part of the .NET framework so it's available in unity, but I seem to remember that you have to specify using the full .NET framework (not just the subset that unity normally likes to use) which would probably increase filesize a bit, but I don't know for certain.
  • edited
    Hmmm I did a few quick tests. (I was worried for a bit that it may be true).

    A web version that uses the serializer with basically nothing else builds to ~300 KB.
    Without the serializer, about ~12 KB.

    PC with serializer 20.3 MB.
    PC without 17.8 MB.

    (Cannot test iOS so quickly, but my gut is that the difference will be larger, although percentage-wise less or the same).

    For PC it works with the .Net 2.0 Subset; for web the API compatibility is fixed at WebPlayer Subset.

  • edited
    @Rigormortis PlayerPrefs can store 1MB of data. I'm not sure that I'm understanding this conversation but it sounds like you feel that's not big enough? (and you are planning to format that data in some inconvenient way to save space?) But I really cannot imagine you coming close to filling that with upgrade keys and true and false values. That would entail tens of thousands of stored values. I obviously don't know your plans, but that's a pretty vast amount. Far more than a game like Diablo 3 stores.

    In my experience (though experiences may differ) PlayerPrefs saved by the Webplayer have been as transient as operating systems (as in I lose PlayerPrefs when I reinstall Windows or MacOsX). So about as transient as a game on a harddrive storing data locally (which of course isn't permanent enough for some games, but plenty permanent for many).

    If you're concerned about publishing and selling the game (at which point users will be more precious about their saves) then you might end up integrating with the IOS Cloud or the Steam Cloud anyway. So whatever solution you use now might in itself be transient.
  • @BlackShipsFillTheSky, my concern wasn't about it being big enough. 1MB of data is more than enough for the types of things I want to store.

    It just felt messy to use for lots of little values. I think PlayerPrefs was designed to store "recent" information, things that don't change often and have a limited set of variations. So my first approach at using playerPrefs was really bad. If I plan a bit better how I'm going to use it, I'm sure it'll be fine.

    As far as the transience(is that a word?) goes...it shoulnd't really be a problem. I sometimes get stuck on insignificant details. Which is why I want to make more threads like this so people can just tell me that I'm being an idiot and I need to move on :P

    @hermantulleken, thank you for doing those test. It's good to see some numbers that show the contrary to what I thought :)
  • edited
    @BlackShipsFillTheSky I'm a pretty messy programmer that way. So the clunkiness of PlayerPrefs doesn't bother me even slightly (and performance-wise, which I do care about, it's plenty fast).

    I consistently eschew the least amount of effort to get anything working fast (and to then deal with the fallout later if the game actually turns out well and needs to be improved). So you can take that into account whenever I (perhaps misguidedly) give programming feedback :P
  • @BlackShipsFillTheSky, I talk to myself as well but I tend to do it when I'm alone in my room...not online :P

    Any feedback is always appreciated, even if it might be misguided. :P It sometimes really good to get another perspective, especially if the other perspective doesn't value the things your own does as much as you do. That way you can get some interesting new avenues to explore(maybe).
    Thanked by 1EvanGreenwood
Sign In or Register to comment.