Is there anyway to save binary or text data to the iPhone? Or can you create an AssetBundle on the iPhone using BuildPipeline.BuildAssetBundle()?
What you would usually do is using the PlayerPrefs to save and load data on the iPhone (I had that same question at the session on iPhone development at Unite 2008)
I tried using PlayerPrefs and it works perfectly in the unity editor, but when I build it to the iPhone, it doesn’t work. Any other steps involved?
Nope, file a bug I guess.
I was wondering about that too… anyone had any Luck with saving PlayerPrefs?
Please post the results of your solution (if you got any) on this thread.
I’m also interested in getting this working, and I guess a lot of people would be interested in this
Using the PlayerPrefs should be straightforward - if it doesn’t work I would consider this a high priority bug. I won’t get to play with the iPhone version during the next 10 days as I am offline (writing this from my iPod touch) but that’s one of the first things I’ll be looking into when back as I need the ability to store files for a client project…
I absolutely agree - being able to have a player come right back to where he was in a game is critcial for the success of the design and commercial sales.
Please keep us informed on developments with this.
Hi Guys,
I’m a long time reader of the forum, but now I feel I finally have something substantial to contribute.
While the PlayerPrefs class also doesn’t work for me, I managed to write and read back data to and from the iPhone. Just create a file to write to in the /Documents folder of the application root, the code below explains how to do this.
The code is not pretty (and doesn’t work from inside the editor), but it gets the idea across. Also ignore everything SimpleLogger related, it is my own quick and dirty object to display logging information on the iPhone screen, I feel pretty much blind on the device without it.
SimpleLogger.WriteLine(Application.dataPath);
// Application.dataPath returns something like "/var/mobile/Applications/30B51836-D2DD-43AA-BCB4-9D4DADFED6A2/Data"
// Strip the "Data" part and add "Documents" instead (done in a very ugly way)
var path = Application.dataPath.Substring(0, Application.dataPath.Length - 4) + "Documents";
// Write a file (btw. add import System.IO; to use StreamReader/Writer)
try {
SimpleLogger.WriteLine("Path is: " + path);
var sw = new StreamWriter(path + "/test.txt");
sw.WriteLine("Testing 1, 2, 3");
sw.WriteLine("And 4");
sw.Close();
}
catch (err) {
SimpleLogger.WriteLine("Write error");
SimpleLogger.WriteLine(err.Message);
}
// Read a file
try {
var sr = new StreamReader(path + "/test.txt");
var line = sr.ReadLine();
while (line != null) {
SimpleLogger.WriteLine(line);
line = sr.ReadLine();
}
sr.Close();
}
catch (err) {
SimpleLogger.WriteLine("Read error");
SimpleLogger.WriteLine(err.Message);
}
Also, check out the following page on the Apple Developer site, it explains a thing or two about files and data management on the iPhone.
Cheers,
Jakko
Nice!
Also: the SimpleLogger is a good idea, does it just dump stuff on screen or what else does it do? tell us more about it! :]
Yep, just a singleton object with a static interface to dump strings on screen (attach it to GUIText object). Pretty simple stuff --hence the name-- but handy anyway.
class SimpleLogger extends MonoBehaviour {
static var instance : SimpleLogger = null;
static function Set (text : String) {
var sl: SimpleLogger = GetInstance();
if (sl != null) sl.guiText.text = text;
}
static function Clear () {
Set("");
}
static function Write (text : String) {
var sl: SimpleLogger = GetInstance();
if (sl != null) sl.guiText.text += text;
}
static function WriteLine (text : String) {
Write(text + "\n");
}
// Returns instance to singleton object
static function GetInstance() : SimpleLogger {
if (instance == null) {
instance = FindObjectOfType(SimpleLogger);
// Failure check
if (instance == null) {
Debug.Log ("Could not locate a SimpleLogger object.");
}
}
return instance;
}
function OnApplicationQuit() {
instance = null;
}
function Awake()
{
Clear();
}
}
Cheers,
Jakko
Wow- how could this possibly get past testing? Anyone at Unity have any comments on this? Not being able to save state is kind of a show-stopper, especially in the iPhone where an incoming call will kill your app.
I can save state in game across scenes, but exiting and coming back into the game seems to clear everything. Is there a call I am missing?
Thanks for the work around Jakko!
Just so everyone knows… The iPhone dev team rejects game apps that don’t save state when the app is terminated or paused because of a phone call. How do I know? Because one of my apps was rejected a month back… and I had to add those features in for them to approve the game.
So if you plan on putting your game on the App Store… you may want to write Unity to have them include this feature (if it’s not there) or figure out a way to save state when “onAppWillTerminate” is called from the app.
I can’t develop with Unity if i know there’s a 100% chance that my app will be rejected. And as of right now… there is a 100% chance it will.
We will make the PlayerPrefs class work with the next release very soon.
Until then use the solution posted above.
That said, most games on the AppStore do not persist state when exiting. So this being a requirement for publishing is just not the case.
Thanks very much Joachim for the update!! That’s great news. But I would like to state that I still have the rejection email stating that game state needs to be retained. I’m sure this all depends on the mechanics of the game. My game for example wasn’t like a puzzle or quick one play type game. You had to spend a lot of time doing something to accomplish a goal. Because of that Apple felt state needed to be saved constantly… or at least when the app suspends.
If you visit iphonedevsdk.com and read the forums … many other game developers have had this problem.
Yup. None of my three current games or the two I’m about to push to the store have a save game state at all. I’ve yet to have an app rejected (fingers always crossed).
As an example motochaser which is featured in a lot of Apple’s commercials, does not enter back.
Anyway it’s definately useful to have this and we will have the PlayerPrefs class working with the next hot fix and until then you can also use the solution posted above.
Can we use Mono file i/o routines on the iPhone? (Obviously, restricted to the correct locations…)
Thanks for the replies. The solution that jakkovanhunen posted is great. But I would like to save when the game is terminating.
So currently we don’t have access to the event applicationWillTerminate? And in script we will never know when the application is ending?
I second this question. We now know how to save the game state, but now we just need to know -when- to save it. So I’m assuming the standard “OnApplicationQuit” isn’t the way to go? Or does that still work for incoming calls?