Optimizations


Our biggest issue with creating Butterfly Expedition was performance on the web. The game played just fine on our dev systems natively. Our first web export, however, was stuttering a lot. It was a shocking difference for us. We thought we were almost done with this jam game, and were getting ready to switch our main focus back to Let’Em Run Free. We ended up spending an extra 2 days focused mainly on performance. We had also originally planned to not do much updating after submitting. While we did sort out performance enough to submit a playable game, it still had more lag than we liked, and was not really playable on mobile. We went ahead with using Butterfly Expedition as a test platform to learn more about the issues that had caused the poor performance.
Our main issue was the size of our tile maps (TileMapLayers). We started by just laying out a big area of the ground tiles to work with and seeing how far we could run in a game day, with the idea that each day the player would go one direction from camp. We added many trees to make a forest that defined the paths, and then layered on decorative tiles such as flowers and rocks, including animated flowers. This resulted in a lot of tiles. We had not really thought about tile maps and performance, so just filled the map to make it full of life. As we looked into the issues we started to read about chunking. We broke up our tile maps so that each path was in 2 parts, plus another for the camp and beach, and each got a VisibleOnScreenEnabler2D, though they do still all load at game start. We also disabled the tile map with animations by default, but added an option in the settings to turn it back on for PC. The animations don’t get disabled with the rest of the tile map and were causing some of the issues. We also went through and removed extra tiles that we did not need, especially those that the player would never see. To further reduce the number of tiles, we also converted the base ground layer to a large image. We made a 1000 x 1000 pixel ground image, and tiled it over the play area. The beach and water tiles were then placed over these, where needed. The physics were disabled for most tile maps and we replaced them with some StaicBody2Ds and CollissionPolygon2Ds. In addition to the tile maps, the audio was also an issue. The biggest change we made for the jam release was to preload all the music as samples when playing on web. This reduced the random stuttering we were getting the first time each was loaded. These changes were good enough to get the game ready for submission.
After submitting, we decided that rather than switch back to other projects, we would learn what we could to improve our future games. We split off a separate version of the game for testing with and looked at ways to not only improve performance, but also make the changes easier to work with. For the submission, we had manually chunked the tile map from the original. While it worked, the chunks could have been smaller for better optimizing. Also, any edits now required switching to the right tile map. My first focus was on a better way to chunk the tile maps. I saw a lot of advice to do chunking, but was not finding any good examples to work from. The basic idea seemed pretty simple, so I decided to try making my own. I wanted to be able to develop from a single tile map, or at least larger chunks, and then let the tool cut it up into smaller pieces and add the VisibleOnScreenEnabler2Ds. It was designed to be the parent of the tile maps to be chunked. On ready, it will loop through all of its children, and any that are TileMapLayers will be divided into chunks. There are settings for how many cells should be in a chunk, and the margin for the enabler. This does add a bit of a delay to startup, but was not too bad on the dev systems (under 1 second). On mobile it can be too long, though further refinements have decreased the time. It would generally not be something to keep in place for a release build. When ready for release, we run the project and go to the remote view. There we can save the chunked tile maps as their own scene. The game can be stopped and we can then replace the non-chunked tile maps with the chunked ones. Of course, we save the non-chunked ones before removing them. The new chunking resulted in much improved performance, especially using mobile.
While the chunking did improve things, we still had a lot of tiles. We were making a forest with individual trees. The next thing that seemed like it could be improved was to reduce the number of tiles. Instead of individual trees, we wanted to create pre-made groups of them that would be placed as the bulk of the forest. Then the individual trees would fill in where needed, as well as defining the edge of the path. The base tile set is 16 x 16, though most trees are larger than that. We ended up deciding on having 2 bulk tree layers. One would be 256 x 256, and the other 128 x 128 to fill in smaller areas. We did these as 2 different tile maps, but it might have been better to do a single one at 128 x 128 and use patterns for the 256 x 256 clusters. Ideally we wanted to use the tile map tools to create a bunch of these larger images. We looked for a tool to create these, but did not find anything that worked well for us. I’m sure there are tools like this out there, but we were not having luck in our search. In the end we used some of the chunking logic to create a tool that allowed us to export these clusters of trees as images. This tool has a tile map of its own that uses a single tile of the desired size to mark out the area to create the clusters. Another tile map is then added with the tile set of what you want to create the clusters from. You can have multiple tile maps setup (generally hiding those not currently in use), though it only processes one at a time. In the parent you select which tile map to create from. You then place your smaller tiles inside the marked areas, making sure any oversized tiles are fully within the borders. For new cluster tiles that are only a single cell, there should be a gap of at least 1 cell around them. When saving, these individual tiles will be put together in a single file in a square shaped grid. If you create a rectangle of marker cells, it will save them together as a separate image (PNG or WebP). In this way you can create larger patterns to use in the tile set. We used a 128 x 128 marker size, but also created the 256 x 256 clusters by using a 2 x 2 grid of them. We could also have just used a 256 x 256 marker tile set, but doing it this way let us create both sets together to more easily compare them. The tool, and our technique, still need some refining, but it did the job well enough for now. Since many of our images were oversized and could not go right up to the edges, after loading the images into the tile set and selecting them, we reduced the tile set size a bit to allow some overlap to better blend the clusters into a more natural looking forest. Of course, one issue with using these clusters/larger images is that you do need to keep an eye on the z-index/y-sort as you place things. How you design the clusters, and the size differences, will have an impact on how much of an issue this is. We tried to patch this change into the existing map, so did run into a number of spots that needed fine tuning. In the future we will design our maps differently to better work with these tools.
In the jam version the ground image was all grass. We added some water and beach tiles over it by the boats, but the rest could not be seen. With our plan to add a map showing the whole island, we needed to update things to show the water around the island. We used a tile map to create the updated design, then used the image cluster tool to export it as a single large image. We merged the grass ground image and the new water/shoreline image. That was then run through the tools to break it up into smaller pieces and, with a slight tweak, placed into position automatically as Sprite2Ds that we saved as a Scene from the remote view. We ended up with a decent base ground layer with the grass and water, but only using some reasonably sized images, rather than a lot of tiles.
To deal with the animated tiles not stopping when off screen, we changed them to AnimatedSprite2Ds and used a TileSetScenesCollectionSource to add them to the map. We set them up as a single Scene with a script to randomly pick which animation to play.
Web on mobile shared, but amplified, many of the problems that web on PC had. It also seemed to have a greater issue with our music transitions. Each area has its own background music. As you switch areas, the current music fades into that of the new area. We initially had 2 AudioStreamPlayers which would load the correct tracks as needed. This had the most noticeable stutter when transitioning, so we switched to a player for each track. The ones not in use were set to pause, instead of stopping. While this worked for PC web, on mobile it still seemed to have a stutter when transitioning. We’ve not found an ideal fix for this. For now, we added an option to disable the transitions and just use the camp background music. In addition to the background music, we also have 4 players for the background sounds of wind and animals. These do not seem to have as much of an issue, though they do change streams at the end of playing the current stream, rather than transitioning while playing. We will be revisiting the audio stuttering in the future, and for now will be less likely to do this kind of music transition in other games.
In the end, a game we had intended to only dedicate a few days to, took a lot of our time over the past 2 weeks. While it was not the plan, it was good for us. We learned a lot about performance and optimizing our tile maps, as well as audio on web. We’ve only been doing full time game dev for about 2 months, with it being a hobby before that. There is still a lot we have to learn, and this taught us some valuable lessons. With the Godot Wild Jams being monthly, we were hesitant about doing another so soon, instead of staying focused on the game we wanted to get to release. Considering all that we have learned during this jam, we are rethinking things and will likely continue to do these jams more often, to work on developing our skills in different areas. We will base our participation in part on the theme and if we have an idea we think we can make into a fun game, as well as if it fits with skills we want to work on.
Get Butterfly Expedition
Butterfly Expedition
Help collect butterflies for our conservation program.
Status | Prototype |
Author | Dragon's Isle Software |
Tags | 2D, Godot, Pixel Art, Short, Singleplayer |
Languages | English |
More posts
- Post-Jam Update6 days ago
- “Small” Projects Can Grow14 days ago
Leave a comment
Log in with itch.io to leave a comment.