We’ve finished our game that we had to do for an event it runs entirely within a browser, and as we began to test it, it worked great on the following hardware:
Steam deck, Lenovo laptop, HP laptop from 8 years ago, Samsung S21 FE, A few Xiaomi phones, a Windows pc running Firefox or Chrome.
However, on iOS only, the game just randomly crashes, refreshes the page, then sometimes it gets into an infinite loop of just refreshing the page before the game even loads properly until Safari says that too many errors occurred so the page can’t be displayed.
We tried to debug it with a Macbook, but we don’t see anything in the console, no exception thrown or anything, and we can’t reliably reproduce the issue.
Once again, the game seems to work perfectly fine, even on older devices. It’s only seems to be broken on iOS. Is there a way to fix this? We barely have a month left to get this game into a working state and a decent percentage of our audience seems to have an iPhone.
Can you actually get it to crash on macbook safari, or is it only crashing on iOS safari?
It’s worth noting that all browsers on iOS are safari with skins, so you should see the same crash in “chrome” or “firefox” or any other browser on iOS. Some of those other skins may have better dev/debug tools?
Depending on how you’re getting it onto the phone, you might check the package integrity, if there’s a server maybe check the server logs… see if you can see a way that it could be coming into the browser corrupt?
Timing can also be a thing; I don’t know how browser stuff behaves on iOS, but in full apps there are a lot of things that will make the OS murder your app. Taking more than (IIRC) 5 seconds to respond after app load, for example. It might well be that your preload() commands are making it take too long to light up the page and the OS gets an itchy trigger finger…
There’s also an excellent chance it’s an out-of-memory problem. You could build a custom iOS app that’s just an empty diagnostic tool that just (a) prints load info, and (b) complains if it gets a memory pressure warning. Those would let you know if the phone’s memory was running out, which is one of those things you don’t have a lot of control over or visibility into from the browser.
I’d also suggest maybe seeing if you can dig up the oldest, lowest memory ipad that will still run a current version of the os, and see if you can reproduce on that.
We’ve already used the Mac debugging tools connected to the iPhone to try and check the browser logs, but unforutnately that did not help at all. The engine seems to crash silently with no error messages printed to the console at all, and there’s seemingly nothing wrong, so it’s almost impossible to even find out what’s causing it. It also seems to be completely random, not tied to any specific action, it just crashes after some time.
I know for a fact we do not have a memory leak. As I mentioned in my post, the game works perfectly fine on all other devices, including really old xiaomi and samsung phones, as well as old PCs with slightly older browsers.
I wasn’t suggesting a memory leak, I was suggesting the phone was running out of memory. iOS doesn’t have swap, so if the programs running on the phone exceed available physical memory the OS gets the shotgun out. If your game takes somewhat close to the amount of memory the phone has available, then whether the OS kills it or not is going to depend on what else is running, what’s in other tabs in the browser, and so forth.
When memory gets close to running out, iOS sends a memory pressure warning to all running apps that basically says “if someone doesn’t free up some memory, I’m gonna start shootin’, and it might be at you”. Native stuff gets that signal (it’s in the app delegate), but as far as I know web stuff doesn’t, so from your point of view it would be silence and then your game disappearing with no warning or explanation.
So, if you make a little app that just listens for a memory pressure warning and complains about it, then if it’s running when your game does and your game crashes, you can see if the memory canary complained. If so, it’s (probably) the OOM killer terminating your game. If not, well, back to the drawing board, I guess.
This would make sense except for the fact that, as I said, the game runs even on an old android device with 1 GB of RAM in total. If the issue was memory, then it should be able to run perfectly fine on an iPhone 15 Pro Max, which is what I have to test things on, and it should crash even faster on said old Android device with just 1 GB.
Fair enough. @midiphony 's link definitely seems worth checking out, though the load loop thing you’re seeing makes me wonder if it’s a different problem.
One thing you could try is making a minimal native app that just displays a webview, and load your game in that. Hopefully that would give you access to any errors and diagnostics that the full user-facing browser. You could also (if you haven’t already) turn on developer mode on safari, which would hopefully give you a bit more to work with. It’s in settings->apps->safari->advanced->web inspector, I believe.
After some debugging it seems to be an issue related to network speed / fetching assets.
Removing all of our large assets seems to work and the game no longer crashes. Putting just a few assets back still works, but if the game needs to stream in more than about 100mb then it just times out on iOS, and only on iOS. This is still a platform specific issue and something with Godot though.
I’m curious if the large assets you removed included audio files! In my case I was only able to get the crashing/reloading to stop by disabling all audio (even if my audio file sizes were very small).
My solution for now is to just use Godot 4.3 for web games since my exports from there seem to work fine on iOS mobile browsers.
(I’m the one who posted about the same issue, linked above)