Now that I’m receiving real art for my game, I thought it would be a good time to learn about memory usage and limits. This was also prompted by my current level running at 55-60MB before any gameplay action or characters loaded on screen. That memory usage seemed a bit high, so I decided this was an issue that I needed to delve into. In hindsight, most of this is basic to an experienced game developer, but I found the process to be quite fun. You can just read my lessons learned below if you don’t want to follow my detective work.
- Product -> Clean in Xcode between each test.
- Upper limits on memory usage.
- Compress png’s to improve download size, not memory management.
- PVR is a commonly recommend format.
- Change build settings to RGBA4444 if your images still look good at that setting. I’m not sure if it is my art style, but I couldn’t get them to look right (even with dithering).
- RGB565 seems to hold up quality, but does not support transparency. This would work well for my base background.
- Breaking apart large images into tiles, and removing tiles that would be covered by other gameplay elements, shows minor gains.
- Create a smaller file for smaller resolution devices as fallback.
- Group files in texture atlases according to use.
- Read official advice.
Of course, nothing is ever easy. Here are my unanswered questions:
- Sprite Kit seems to convert atlases at build time, so setting one image to be RGB565 won’t work. It’s all or nothing. I tried adding my one image to images.xcassets, but memory usage increases since the benefits of atlases aren’t being used. I’m trying to find a way to set different compressions for different atlases.
- I am not having any luck getting PVR files to work with Sprite Kit. Any tips?
Test 1: Remove GUI
I began my tests by removing things piece by piece. The goal was to get down to 1 node and observe what happened along the way.
Memory: 52MB CPU: 17%
Test 2: Remove Layers
My game is isometric, so there are a ton of layers to give depth and allow units to walk behind objects. I went ahead and removed all of those, which leaves a basic full size background image. This had hugely successful results mainly because anywhere a layer is sitting gone top of the background, the memory usage for that part of the screen is essentially doubled.
Memory: 25.5MB CPU: 14%
Test 3: Compress Images
Using compressor.io, I shrunk my background image from 1.93MB to 390KB. That’s a huge difference, and I was expecting huge results. But, I didn’t get the results I was looking for. Hmmm. At a minimum, this at least helps with the over-the-air download limit.
Memory: 25.5MB CPU: 12% Verdict: Helps download size, but not in game memory.
Test 4: Clean Up Atlas Folder
I was using my
.atlas folders to hold generic items instead of specific collections. I removed everything not necessary to the scene, and noticed good results. It appears that if you touch anything inside of an atlas, the entire contents of the atlas are accessed in some fashion.
Memory: 20.9MB CPU: 12% Verdict: Important.
Test 5: New Swift / Sprite Kit Project
Making progress now, so a benchmark is needed. What does a brand new, empty project run at?
Memory: 8.1MB CPU: 9%
Test 6: Clean Up images.xcassets
Since cleaning up the texture atlases helped, I decided to see if cleaning up images.xcassets would have a similar effect. No luck.
Memory: 20.9MB CPU: 12% Verdict: Not related.
Test 7: Stop All Code
I made sure that all of my code was no longer executing. The scene is unpacked, and then nothing else happens. No change.
Memory: 20.9MB CPU: 12%
Test 8: Try A Smaller Background Image
At this point, it became clear that file size alone is not the only indicator of memory. So, I tried an image of 1⁄4 the size. 75% savings, which proved that the remaining ~12MB between a base project and mine was due to the texture size of the background image. Turns out textures use memory based on their resolution and color depth.
Memory: 11.8MB CPU: 11% Verdict: Huge. Memory is related to texture size.
Test 9: RGBA4444
Using RGBA444 instead of RGBA8888 cuts the memory used in half. The problem is that it leaves artifacts all over the artwork, and in my case they are quite noticeable. I pointed out the water and snow as examples above.
Memory: 14.9MB CPU: 11% Verdict: Huge. But, image quality suffers.
Test 10: Break Apart Into Tiles
I wanted to see what would happen if the background was tiled instead of one giant image. Then, I could remove tiles that would be hidden behind a z-index overlay. I thought this would be significant, but I only saw minor gains.
Memory: Saved 1.8MB CPU: 11% Verdict: Minimal gains. Last resort.