Having a SAVE feature in a project/game is one of the common things that could lead users to be more attracted and increase replay value for potentially recovering what was done in a previous visit. Using the SharedObject class in actionscript project/games is sometimes a requirement or at least a need, may it be AS1 (FP6), 2 or 3. It can be used to store valuable data like progress, settings, statistics, achievements and a lot more without dedicating storage on the server. Basically, SO or shared objects are like the browser cookies for flash, it is used to store some amount of data on the user machine, therefore it also has some limitations on its use (for security purposes really).
By reading the documentations or the livedocs, either for AS2 or AS3 (it’s really the same), you might have a gut start of what key points to remember.
- created shared objects can only be stored/retrieved on the same domain
- shared objects cannot be shared across domains, meaning a shared objects from “examplesite.com” cannot read shared objects created by another domain “mywebsite.com”
- users can disallow local storage per domain or opt-out globaly, then the object would not be saved locally
- data size to be stored is limited by which the user sets it (none, 10kb, 100kb, 1mb, 10mb, unlimited), although a dialog box can request an increase in storage if what is set is exceeded
- if the user sets a limit smaller than the shared object, the shared object would be deleted
- shared objects are stored on the user’s local machine not on the server, something shared over another machine cannot be accessed by another machine
The most essential part when using SharedObject is the SharedObject.getLocal() method, which is what we will be discussing more through out. Basically, AS1/2 and AS3 syntax haven’t really changed (although a few more rules were imposed in as3).
getLocal(name:String, localPath:String = null, secure:Boolean = false):SharedObject
[static] Returns a reference to a locally persistent shared object that is only available to the current client.
var mySo:SharedObject = SharedObject.getLocal( 'mySaveName', localPath, secure ); mySo.data.thingtoSave = myVariable; // your variables mySo.flush(); // stores data into disk
Avoiding Known Issues
It might seem that using shared objects could be the simplest when you are only storing a couple of variables and objects like statistics or even could be the more complex when saving a game progress/state together with the players preferences. The bigger the system, more likely, the more complex your variables/objects are (same for games), and this is where possible issues during saving/loading/handling the shared objects.
Some common things to remember when using shared objects with your games:
- Don’t use direct reference to objects; only save the game’s data, not the actual game objects.
- Use a localPath param on the
getLocal()method. - Taking advantage of unique names for your shared object name.
- Prompt and request for shared object size limit increase when your game needs it.
While I only have these that I can explain, you are free to share more if you have one or more. We can discuss and make the lives of other actionscript writers a little better.
Don’t use direct reference to objects; only save the game’s data, not the actual game objects.
Why do I say this? Basically it is fine to store various data types such as objects and arrays on SO (shared objects), same goes for strings, numbers (int/uint), booleans and bytearray (as3). If you store references to local game objects on your shared objects, one way or another, your in for a later problem.
var mySo:SharedObject = SharedObject.getLocal( "mySaveName" ); // world.gameObject contains further objects like settings, player, etc mySo.data.gamedata = world.gameObject; mySo.flush(); // --
When you do something like the above, instead of storing the needed values only, you are referencing the local game object (w/c also contains references to other local game objects) in which Flash defines this as a copy of the local object but is really just a reference. Any change through out the game values/data would update the local object (which the shared object references) and Flash Player would write that into the shared object file when flush() is called or as soon as the shared object session ends – that is then swf file is closed.
The worst case here is that when you clear, reset or even delete your local game objects, the shared object which references to it will be affected and updated (as session has ended).
Also, even if you don’t experience the immediate issues when you do the above there, a problem might still arise when you load the shared object in a later time. This case might not be so common but is possible to experience if loading the shared object is sloppily made. You can have inconsistent object references where the object contained within loaded shared object is conflicting, a duplicate, or not referencing the correct object.
A better and safest way of using shared objects (something like):
mySo.data.gamedata = { player:{ score: world.gameObject.player.score, health: world.gameObject.player.health, currentLevel: <code>world.gameObject.player.currentLevel }, settings:{ mute: world.gameObject.settings.mute, quality: world.gameObject.settings.quality, particles: world.gameObject.settings.particles, } } /* well this is just a shortcut on containing them into objects, * but the point here is that score, health, currentLevel, etc * are all basic data types like number/int/uint, string, bool, etc</code>
Now you see that we store each valuable data only. We now transfer only the value of the variable not it’s reference. So while it’s fine to use objects and arrays on your shared objects, keeping be wary of how you do it, be careful.
You probably wouldn’t want to directly store instances of display objects, bitmapdata, functions, etc on share objects.
Use a localPath param on the getLocal() method
While passing the localPath parameter upon calling getLocal() is optional, although I would have to recommend using it by this time. In the case where you are building an independent system, prototypes, does not consider expansion/addons and will never be a part of a larger system, you can probably opt-out the localPath and never mind it.
So whats the issue of using and not using the localPath? By default, if you leave localPath by it’s default (null), it would use the the full path of the swf file (w/c includes the swf file itself) to store your shared objects.
#SharedObjects/<random code>/<domain>/<path>/<swf filename>.swf/<object name>.sol
- Windows XP and Vista:
- For Web sites: %APPDATA%\Macromedia\Flash Player\#SharedObjects\<random code>\<domain>\<path>\<object name>.sol
- For AIR Applications, %APPDATA%\<AIR Application Reverse Domain Name>\Local Store\#SharedObjects\<flash filename>.swf\<object name>.sol
- Mac OS X:
- For Web sites, ~/Library/Preferences/Macromedia/Flash Player/#SharedObjects/<random code>/<domain>/<path from webserver>/<object name>.sol
- For AIR Applications, ~/Library/Preferences/<AIR Application Name>/Local Store/#SharedObjects/<flash filename>.swf/<object name>.sol
- Linux/Unix:
- ~/.macromedia/Flash_Player/#SharedObjects/<random id>/<domain>/<path>/<flash filename>.swf/<object name>.sol
-taken from wiki
For example, I have a swf at http://example.com/games/uploads/supergame.swf, and when it creates a shared object (SharedObject.getLocal("supergameData");), the SO can be found at #SharedObjects/<random code>/example.com/games/uploads/supergame.swf/supergameData.sol.
While it works well and fine without the localPath parameter, there are certain sites/APIs/services that change the game’s file name by using their automated uploads, feeds, etc as the file name is used in the path. When the developer tries to upload a bug fixed build (v1.0.1), the swf might have another file name hence a problem appears where the previous build’s (v1.0.0) shared object won’t be accessible from the new build due to security reasons.
Although your shared object would be secured against any another swf so it can’t read it, by setting a localPath parameter like “/games” or simply “/”, the shared object can now be read by another swf file within the same domain. Using “/games” would make the SO accessible for any swf within the game directory, while having “/” would make it accessible from any swf within the domain.
Again from the same example but using SharedObject.getLocal("supergameData","/");, makes the SO at #SharedObjects/<random code>/example.com/supergameData.sol. This would make it not dependant on the swf’s file name.
Note: If you set a localPath in which the path doesn’t physically exists as a (sub) directory of the domain the shared object won’t be stored. Luckily with AS3 you’ll be prompted with an Error #2134 when the SharedObject can’t be created, but for AS2, you have to be well aware of this.
Taking advantage of unique names for your shared object name
This is one is something that I have just learned through experimentation and will soon incorporate on my next projects. While setting the localPath parameter to “/” makes the SO accessible to other swfs, there is also a risk that your SO name might be the same with another swf. We wouldn’t want another swf to mess up or overwrite our SO file just because it both uses general and/or generic SO names like “saveData” or “gameData“.
The ultimate tip: Since the SO names allow certain special characters like / (slash), we take advantage of that! Together with the localPath “/”, what I recommend is do a standard setup for your SO names something like:
<company/developer name>/<game name>/<data name>
var mySo:SharedObject = SharedObject.getLocal( "jaycsantos/neolithic/preferences", "/" ); // -- and/or something else like var mySo:SharedObject = SharedObject.getLocal( "jaycsantos/neolithic/gameData1", "/" ); // --
…will store your SO at something like: #SharedObjects/<random code>/<domain>/#jaycsantos/neolithic/gameData.sol
Although I still have to confirm this with Mac OS and Linux machines. Drop me a line if you find it working with those.
Now ain’t that a little more organized than having all SO on the “/” of the domain!
Prompt and request for shared object size limit increase when your game needs it
There are cases when your shared object has a lot of data in it and it could exceed the default 100kb limit of a user. If this happens, it may cause your shared objects to be written but not read. I have read quite a few times where issues of reading/writing of share objects were resolved by prompting a request to increase local storage limit. This is where the flush() method takes it stand.
Immediately writes a locally persistent shared object to a local file.
AS3
flush(minDiskSpace:int = 0):StringminDiskSpace:int (default =0) — The minimum disk space, in bytes, that must be allotted for this object.AS2
flush([minDiskSpace:Number]):ObjectminDiskSpace:Number [optional] – An integer specifying the number of bytes that must be allotted for this object. The default value is 0.
With AS3, the flush() method basically does the same thing as with AS2 including their parameters, the only difference made was their return values. AS3 returns a string constant but AS2 returns an object; still their purpose is the same, only the data types have changed.
Returns
SharedObjectFlushStatus.PENDING: The user has permitted local information storage for objects from this domain, but the amount of space allotted is not sufficient to store the object. Flash Player prompts the user to allow more space. To allow space for the shared object to grow when it is saved, thus avoiding a SharedObjectFlushStatus.PENDING return value, pass a value for minDiskSpace.SharedObjectFlushStatus.FLUSHED: The shared object has been successfully written to a file on the local disk.
AS2:
Returns
true or false; or a string value of “pending“, as described in the following list:- If the user has permitted local information storage for objects from this domain, and the amount of space allotted is sufficient to store the object, this method returns true. (If you have passed a value for
minimumDiskSpace, the amount of space allotted must be at least equal to that value fortrueto be returned). - If the user has permitted local information storage for objects from this domain, but the amount of space allotted is not sufficient to store the object, this method returns “
pending“. - If the user has permanently denied local information storage for objects from this domain, or if Flash cannot save the object for any reason, this method returns
false.
var mySo:SharedObject = SharedObject.getLocal( 'mySaveName', localPath, secure ); mySo.data.thingtoSave = myVariable; // your variables /* stores data into disk and require 10kb of min space * if the allocated disk space for local storage is * less than 10bk which most probaly be 1kb, then it * would prompt a dialog box requesting for an increase */ var fushResult:Object = mySo.flush(10000); trace( fushResult );
So saying simply, if you know your game’s shared object will be greater than a few kbs, you should consider using flush(minDiskSpace) with as your expect maximum size for your data. Why maximum? – think of it as your allowance. Now don’t even consider 2mb or more as an allowance if it’ll never even reach it, play your game at it’s fullest and see what is the size of the shared object using the getSize() method (as2) and the property size (as3) then add around 5-10% of it’s size for an allowance.
Conclusion
After all I have read about using SharedObject is as simple as it could be, in reality it can be a whole lot more than spinning circles for all of what you would need. Well yes, storing a string and recovering it is a piece of icing but storing a complete game state/progress is a new kind of cake to bake. Basically what I have written here are tips and suggestions that I have experienced and with what I have experimented. Either it be accurate or I know not, using SharedObjects has its own work around and is not as simple as most people have said like building a chair, while yes it is not the most complicated but it could be a big question mark on the head for someone new or not familiar to its purpose. I might even consider making a SaveManager or the like but that would be when I get to it. Well, that’s it, this one is quite long but I know it’ll help!
Other Keywords
- Working with Flash Actionscript Shared objects.
- Issues and techniques with Flash Actionscript shared objects.
- Saving data with action script using shared objects.
- Actionscript tips and tricks, shared objects.
- Shared object help, actionscript 2 & actionscript 3.
- Flash actionscript saving & loading locally.
- Flash Actionscript proper way of use when Shared Object does not work.




•
26 Apr 09 at 12:22 am
Thank you!! This tutorial really helps me alot! These will save a lot of developers from frustration because theirs save features screw theirs game!
27 Apr 09 at 12:04 pm
Even I had my troubles when I google about SO. Most of what is written is from my experiments. Glad it could help.
3 May 09 at 6:25 am
Jayc this is so great! Thanks for writing all this up.
3 May 09 at 9:20 pm
No problem mate.
I might have to do some more research and experiments to look for more issues and stuffs about SO’s – with time in mind though.
19 Jun 09 at 4:22 am
THis is great! Fixed my problem. I was trying to use SO to skip a flash intro page after you have seen it once before. This was pretty easy until I wanted to add a “replay intro” in flash swfs on other pages. But the pages kept creating their own .sol file and not re-using the variables. So this directory fix took care of that. Thanks!
19 Jun 09 at 12:21 pm
Great that it helped you… so I assume that your pages are separate swf files.
SO files is a royal pain when not seriously dealt with.
19 Jun 09 at 4:29 am
And YES, this does work on Mac. Using Firefox and OS 10.5.7
19 Jun 09 at 12:22 pm
oh great! now I assume that it all works on most machines 85% of the time. And yes that number is just a wild guess without the right proof and tests..
3 Jul 09 at 2:52 am
Thank you! Thank you so much! I have been searching for this answer for a long time! This helped a lot in my video game.
8 Feb 10 at 12:21 am
Thanks a lot! I am checking my code if it violates your recommendations.
10 Mar 10 at 7:17 am
Hi. There is allways a dummy one that cant make it work! I read all about SO. I can save data and recover it at the same SWF. But if I reload it or call another one, data is not there anymore. It incrase space at local storage, but are not recovered. People developing for flash lite use a listener object that call some onLoad function. Why aren’t you using one? Data recovering is so quicly? Anyway, there is more like me in the net, so if you got a suggestion, we may share here. Best regards.
1 Apr 10 at 2:16 am
If you want to have even more space in your SharedObject, use ByteArray with deflate/inflate or compress/uncompress method. I had an xml in Local SharedObject that used to always pop the security panel and now its gone!
Got a nice compress ratio 242421 bytes to 35535 bytes after compress for a huge XML.
23 Oct 10 at 1:52 am
Hi is there anyway I can write a MovieClip to Disk via SharedObject or anyother technique and then I can read it in other file…
In short I have Movie Clip in SWF_A I save or write that MovieClip on disk or DB and then I can load that Movie Clip on SWF_B ?
Regards,
Amjad
6 Nov 10 at 9:11 pm
Hi, thank especially for you note about the #2134 error!
Happy coding
17 Nov 10 at 12:59 pm
What more could one ask for, this article did clear me a lot of stuff !
Thanks – JC
12 Feb 11 at 12:54 am
I am having Flash Player 10.2 issues with doing cross SWF shared Object access.
Using KewBee plugin switcher I have it working in 10.1 or earlier but failing in 10.2. If I find a solution I’ll post here. In the mean time any thoughts?
Oh the “Allow 3rd party storage” option is enabled in the global settings
12 Feb 11 at 12:37 pm
Hey, I haven’t encountered it yet but thanks for the heads up with 10.2. I’ll look into it and see if something has to be done, maybe write a new post if its significant.
16 Feb 11 at 8:57 pm
Here is the text of an Adobe Bug I submitted (FP-6193).
“Since CS4 SharedObject will remember what you told it to write but getLocal(…) will not actually go and get the new values from the file. To delete the SharedObject fully and re-acquire it from the file, you need to attach it to a dummy MovieClip which is added to this Class and then removeChild used to throw it out of memory
In Flash Player 10.2 this work around does not work. I use KewBee plugin switcher; 10.1 works 10.2 doesn’t work.
I actually got the shared object file and manually changed a numerical value in the “.sol” file and trace out the results of the get action. 10.1 the file is ingested back into the SWF, 10.2 it is not ingested back into the SWF. The problem exists across browsers, as I have checked Internet Explorer 8, Chrome, Firefox 3.6 and Firefox beta 4.0b11. I have checked plugin Global settings to do with storage and privacy and they all seem to be OK.
This is stopping me from using SharedObjects to manage functionality between SWFs. Surely it would be better all round if the SharedObject just actually got the data from the file when it says it is going to, instead of “remembering” what it thinks the data should be. “
12 Apr 11 at 9:02 pm
I have a similar problem with Flash ‘remembering’ Shared Object data. I need to create an app that checks if SO’s can be stored locally but what happens is, even though the user may deny that data be stored locally, you can still read SO.data.* variables although there is nothing inside %appData%…localhost. This caused a lot of confusion because it could recall data but if you closed the instance it wouldn’t be able to recall the data again. So for a while the program would return false results and say it could store Shared Objects on the machine.
Is there anyway of actually forcing Flash to read from disk, besides say, flushing and using the result to see if it could flush and reading if true else return an error.
3 May 11 at 11:56 pm
Nice tips,
but in your way of saving objects to the Shared object,
how can you retrieve the values?
if I save to So like in your example, and the, try to trace the (mySo.gamedata) i get undefined value
But if i save things to Shared Object like :
mySo.data.gamedata = “data”;
I’m able to retrieve the data
Why’s that?
1 Aug 11 at 4:49 am
Beautiful, solved my problem as well. I have users saving in multiple slots, and couldn’t for the life of me figure why the game was only allowing two slots to be filled. Fixed it right up!
19 Oct 11 at 11:40 pm
I am trying to use the shared object .getRemote() method, but I can’t seem to get it working. Once I got it to say that flash player stopped a potentially unsafe action, does this mean that it worked? I want the data to show up for multiple users. IE, if someone clicks the button, everyone knows that someone clicked it, and how many times it has been clicked by everyone. The button is a movie clip that looks like a button.
9 Mar 12 at 12:30 am
I’m trying to save/load .sol files using the same swfs on different computers. How can I make it so that the .sol file can be loaded from the desktop?
11 Mar 12 at 10:11 pm
I don’t think its possible to share .sol files from different machines, you might be better to check on server services or use the FileReference class if its just loading/saving of files.
11 Mar 12 at 6:03 pm
mySo.data.gamedata = {player:{
score: world.gameObject.player.score,
health: world.gameObject.player.health,
currentLevel: world.gameObject.player.currentLevel
},
settings:{
mute: world.gameObject.settings.mute,
quality: world.gameObject.settings.quality,
particles: world.gameObject.settings.particles,
}
}
Am I correct, in getting the data as
var playerObj:Object = mySo.data.gamedata.player;trace(playerObj.score) //output the score
11 Mar 12 at 10:15 pm
I don’t see anything wrong with that, it should fine.
You can also use xml to organize it easier, if you’re already known to it. I’ll probably write something about using xml on SharedObjects when I get the time.
24 May 12 at 11:33 pm
is there any way to delete SO????????
like i have a few icons in a few positions……..
i have saved the icon’s position in SO using the flush thingy and it is working perfectly……
but when the user presses restore….all the SO files should get deleted……..
how do i do it
9 Jun 12 at 2:53 am
@rahul
just use the SharedObject.clear() method on each of your SO files…