As the Pixelrama levels grew larger we noticed their creation time grew just as much. So we decided to prioritize optimizing the puzzle generation code to improve testing time since it would be necessary before releasing the game anyway.
Finding the problems
After running the profiler and gathering some data, we found out there were two main problems:
- Recursive coloring: when the puzzle generation algorithm finishes running, it leaves the level with all pieces connected as a finished game. Then, we pass through every tile and rotate them two times on average in order to deliver the level ready for the player to start playing. But, rotating a tile is relatively expensive because it triggers the recalculation of its color and their neighbors recursively, causing a big CPU slowdown.
- Prefab Instantiation: for each tile of the puzzle, we instantiate a Unity Prefab. To our surprise, it takes a lot of time to instantiate each one of them, even though its hierarchy its pretty simple (a parent with around 10 children).
After some brain storming trying to find ways to solve those problems, we came up with solutions that seemed very effective and were relatively easy to implement, described next.
To tackle the issue of massive recursive coloring, we just changed those random rotations to NOT recalculate the colors after rotating. Then, after all those initial rotations are finished, we ran a code that would update all the colors just once. This solution lowered the percentage of total time spent creating a level from 50% to something around 0.01%.
This one was a little bit harder to solve, as we could not find a faster way of instantiating a lot of objects in Unity. So we decided to fix it a little bit differently with these two steps:
1. We added culling to the camera, keeping on the scene only the pieces that are visible and reusing those as the player pans the camera. This solves the problem partially because if the player zooms out, it was still necessary to instantiate a lot of Prefabs which still caused a slowdown.
2. We stopped rendering the tiles when the player zooms out to a certain amount (it would be hard for the player to play at this level of zoom anyway) and replaced them with a mock of the puzzle, showing finished regions with their respective colors and white for unfinished parts.
For now, our performance problems are fixed, although some questions arose around these solutions. Would the players prefer to view all the tiles when zoomed out, instead of the unfinished image? Also, how many tiles can we show on the screen at the same time without slowing down older devices?
We think these questions can only be answered by gathering more data by allowing more people to playtest the game, which may happen pretty soon.