I'm attempting to get a game up on Facebook but am getting blocked from releasing due to the error below. The wording "PlayerPrefs will not be saved" isn't in our game so it must be coming from Unity itself. When it comes to Facebook canvas games the game runs within an iFrame on apps.facebook.com. At first I thought it was a permissions issue but when I run commands like "localStorage" from the browser console they work without throwing a permission error. Is this a known and/or avoidable issue? Code (javascript): "Warning: PlayerPrefs will not be saved" test-game.js:9971:5 _JS_Log_Dump() test-game.js:9971 __Z40DebugStringToFilePostprocessedStacktracePKcS0_S0_iS0_iiiiPFvRK11CppLogEntryE() test-game.js:1640812 __Z17DebugStringToFilePKciS0_iiiiPFvRK11CppLogEntryE() test-game.js:1640516 __ZN11PlayerPrefs4SyncEv() test-game.js:2456423 __ZL12SetPrefValueRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERK9PrefValue() test-game.js:2455592 __ZN11PlayerPrefs6SetIntERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEi() test-game.js:2455444 __Z28PlayerPrefs_CUSTOM_TrySetIntP15ScriptingStringi() test-game.js:1720942 __Z6m13325P2t8P2t2iP10MethodInfo() test-game.js:3561747 __Z5m7617P2t8P2t2iP10MethodInfo() test-game.js:3561795 __Z5m4453P5t1032P4t901P10MethodInfo() test-game.js:2634820 __Z5m6782P4t934P4t901P10MethodInfo() test-game.js:2744905 __ZN18VirtActionInvoker1IP4t901E6InvokeEP10MethodInfoPvS1_() test-game.js:2618419 __Z5m4056P4t931P10MethodInfo() test-game.js:2618144 __Z18RuntimeInvoker_t59P10MethodInfoPvPS1_() test-game.js:3584599 __ZN6il2cpp2vm7Runtime6InvokeEP10MethodInfoPvPS4_PP12Il2CppObject() test-game.js:96078 _il2cpp_runtime_invoke() test-game.js:30823 __Z20il2cpp_invoke_method21ScriptingMethodIl2CppP15ScriptingObjectP18ScriptingArgumentsPP18ScriptingExceptionb() test-game.js:1268203 __ZN19ScriptingInvocation6InvokeEPP18ScriptingException() test-game.js:1543429 __ZN19ScriptingInvocation6InvokeIbEET_PP18ScriptingException() test-game.js:1543366 __ZN9Coroutine3RunEv() test-game.js:1531504 __ZN9Coroutine17ContinueCoroutineEP6ObjectPv() test-game.js:1531452 __ZN18DelayedCallManager6UpdateEi() test-game.js:1230937 __Z10PlayerLoopbbP10IHookEvent() test-game.js:1440392 __ZL8mainloopv() test-game.js:2457898 dynCall_v() test-game.js:4015770 Runtime.dynCall() test-game.js:277 Browser_mainLoop_runner/<() test-game.js:10117 Browser.mainLoop.runIter() test-game.js:6159 Browser_mainLoop_runner() test-game.js:10113
From what I know, PlayerPrefs cannot be used on WebGL (at the moment). Our game wrapped PlayerPrefs usages in another class early on (even before WebGL), so now we can swap out PlayerPrefs using some other mechanism of our choice. For example -- use localStorage for storing key/value pairs on WebGL.
PlayerPrefs should work in WebGL -- backed to the IndexedDB file system. Does it work when you try it outside of the facebook iframe?
Yes PlayerPrefs work in WebGL in most cases, but not all. For example, games hosted on kongregate.com have all their files hosted on a cdn where the domain is konggames.com, but the page loading them into an iframe is at kongregate.com, PlayerPrefs will just not create an IndexedDB in this situation, and it won't give any error messages either. If you select the iFrame in your Developer Console and enter the localStorage command, you'll get an Exception. Spoiler: DOMException localStorage VM2865:2 Uncaught DOMException: Failed to read the 'localStorage' property from 'Window': Access is denied for this document.(anonymous function) @ VM2865:2InjectedScript._evaluateOn @ VM2791:883InjectedScript._evaluateAndWrap @ VM2791:816InjectedScript.evaluate @ VM2791:682 If you use a local proxy like Charles Web Proxy, or Fiddler to change the html that you're being served on their page to trick your browser into thinking its loading the game from the same domain instead of konggames.com, PlayerPrefs, localStorage, and the IndexedDB all work fine and you can see it in the Resources tab of Chrome. Without mapping it locally, you will not even get an IndexedDB for that page at all. EDIT: I realize this doesn't answer the OP's question, just adding what I've noticed to the discussion in case it helps jonas/anyone figure out the facebook issue.
Yes, it does appear to be working outside the iframe. My understanding of localStorage is that it should work within an iframe under it's own domain. For example if SiteA has an iframe pointing to a page on SiteB and SiteB is doing a localStorage call then the information should be stored under the localStorage for the SiteB url, shouldn't it? That seems to be the way it works for a non-Unity canvas. Because the error appeared to be coming from Unity itself I was hoping for more insight as to why exactly it is thrown.
Hi, I am trying to release my first game on Kongregate however it uses PlayerPrefs pretty heavily. I'm looking into Fiddler however I'm at a lost at what I should be doing. From what I understand I want to use Fiddler to convince my browser that the files are being loaded from kongregate.com rather than konggames.com. Can you share any details on how you accomplished the bug fix? Or at least send me to a relevant tutorial? Thanks!
STEPS BEFORE Fiddler 1) load your preview page on Kongregate.com 2) right click outside of the game window and click "Save as..." 3) Save the html page somewhere on your machine. 4) Edit the html you downloaded and search for Code (CSharp): new GameIframe({"iframe_url": 5) Change the domain that it loads the file from konggames.com to kongregate.com and save the file. NOW LAUNCH FIDDLER 1) REPEAT STEP 1 FROM ABOVE 2) find the request for your preview page, select it on the left 3) open the AutoResponder tab on the right. 4) Click Add Rule... 5) At the bottom in the "Rule Editor" change the bottom line to point to where you saved the modified html file. 6) Refresh the page in your browser 7) You should now see 404's on all the javascript, template, data files etc for your game. 8) Now Click Add Rule for a second rule and set the search pattern (Top field in Rule Editor) to this...(important parts in bold, fill in the rest to match what you're 404ing requests look like) regex:http://blahblah.kongregate.com/gamez/blah/blah/Release/(.*) 9) Now in the bottom of the Rule Editor add the folder to your local build and add a $1 to the end of it. ex: C:\xampp\htdocs\mygame\$1 That should be it. If you refresh your page you should see that PlayerPrefs works. Now this is just a step to prove that its the domain issue, you could never get any players or users to do these steps.
Finding the same results, PlayerPrefs work great until the build is embedded as an iFrame, which is commonly the case when publishing to the major portals (Facebook, Kongregate). There doesn't appear to be a ticket for this in Issue Tracker. Can we add this?
I can't get any playerprefs to save in Firefox or Chrome just using the template html file. Is it still the case that they are supposed to work? I get an error message in Edge saying they won't but nothing like that in Firefox or Chrome.
Outside of Edge i think I've found the issue, tested in Chrome, it was some corrupt data in the pref file, my fault entirely.
@Marco Trivellato We have encountered an issue where saving in the playerprefs was not actually saving. Updating a playerpref string and querying during the same session, it was fine. But when refreshing the page we were getting the old value. (Yes we are doing PlayerPrefs.Save(), and we have Data Cache ticket when building WebGL). Tried to make a repro project but couldn't reproduce. Also after clearing cookies and app data, we cannot reproduce the problem anymore. Any ideas what this could be?
@Marco Trivellato We noticed the issue again. And in chrome we noticed there were 3 indexed dbs instead of 1, totalling over 450megs. Clearing all dbs fixes the issue. Not sure why there were 3. (Usually there's only 1 of around 75megs)
@Marco Trivellato, we are still seeing this problem occur. After a while PlayerPrefs does not save to disk any more. It is currently occurring where there is only one indexdb (unlike the other time). So restarting the webgl app, we get the previous state of playerprefs. So players can purchase coins, and if they close and re-open the page, their coins are lost.
@alexsuvorov Hi Alex, Here's a screenshot attached of the current webgl application, with just one IndexedDb. If there was three db you would see 3 IndexedDbs near each other. We once saw 5 near each other too!
I was interested specifically in the name of the database, which has been blurred on the screenshot or not expanded. Which version of Unity are you using?
@alexsuvorov That blurred out part is just a domain name we use for QA testing, and blurred it out on purpose. The last time I saw this happening was on 5.3.4p1. I'm not sure if this is an important detail or not... but the domain points to an Elastic Load Balancer with 4 instances under it.
My case is like this: 1. Playerprefs in WebGL works fine when there's no iframe involved. I can see indexedDB created in inspector on Safari, Chrome, FF. 2.When I run the WebGL build on Facebook canvas (iframe) , the indexedDB is not created on Safari (OSX), but works fine on Chrome and FF. For Chrome, and FF , I can still see indexed DB.
Hello shb. This is expected behavior. Currently it is not possible to access indexedDB from a cross-domain iframe on Safari due to the browser security limitation. The same restriction applies to Firefox prior to version 42. And as this restriction has been already removed from most browsers, there are high chances that it will be removed from Safari in the future as well.
This is still an issue today (Safari 10.1) - Just experienced it now with my game (Unity 5.6 WebGL->Facebook) viewed on Safari on a MacBook. https://forum.unity3d.com/threads/f...data-storage-safari-fail.467691/#post-3044222
Still seems to be an issue..getting the security error unless they enable cookies. Is there no way around this? 3 years later?
Using Google power, there are discussions happening in https://stackoverflow.com/questions/51378486/safari-and-cookies-in-iframe, and workarounds mentioned in https://gist.github.com/iansltx/18caf551baaa60b79206 and https://github.com/vitr/safari-cookie-in-iframe . The security restriction in Safari is deliberate from their end, there is really no way that Unity WebGL builds can circumvent browser security, no matter how many years pass. Apple is heavily investing in their "Intelligent Tracking Prevention" (at https://webkit.org/blog/8613/intelligent-tracking-prevention-2-1/). What might help is if developers let Apple know they should change how Safari works with this respect. The louder the voice coming from several developers is, there is a chance that it raises more sense of urgency and importance in their development team to adjust the behavior. Report issues in https://www.apple.com/feedback/safari.html and https://webkit.org/reporting-bugs/ , along with details of your reasonable use cases that Apple's tracking policy is hurting. As an alternative measure, looking for hosting solutions that avoid utilizing Iframes can help avoid the issue. Also utilizing hosting solutions that use Iframes under same domain, with the sandbox=allow-same-origin security flag might help.
Thanks for the response, Jukka. I wish it were that easy. When it comes to WebGL, hosting canvases through any publisher site (Kong, Facebook, AG, etc) it's just not really possible without iframes; and if it were, you're talking about a LOT of manual effort for a simple update. I think my team has some workarounds as our product deals with multiplayer & servers, so we have settings saved on the server, but for simple things like 'remember me' or audio settings prior to authentication, playerprefs worked flawlessly, except for, of course, browser security errors preventing some folks from even loading in once the player-pref reference was attempted. Is it possible for Unity to better track this with a function that returns whether it is supported without throwing a catastrophic error? Or is that not possible to communicate between the browser and Unity's WebGL engine?
Oh - does Unity currently abort executing content altogether when a failure to save occurs on Safari? That would certainly be a bug. We should in this case be gracefully ignoring, and run the page, but without saving anything. If you are seeing Unity build crashing execution as a result, that's definitely worth reporting a bug.
FWIW PlayerPrefs fails gracefully for us when indexdb is disallowed on Safari (i.e. when the content is hosted in a cross-domain iframe), but CachedXMLHttpRequest.js does not (coincidentally I recently filed a bug report for it). Perhaps they have "Data Caching" enabled?