Construct 3's export optimisations

42

Contributors

Stats

35,009 visits, 53,592 views

Tools

License

This tutorial is licensed under CC BY 4.0. Please refer to the license text if you wish to reuse, share or remix the content contained within this tutorial.

This tutorial is recommended by the Construct team! This means it contains useful, high quality information that will help grow you as a game developer.
Published on 27 Sep, 2017. Last updated 28 May, 2024

You might have noticed that sometimes the Export project option takes a while to complete, especially with larger projects. This is because Construct is working hard to optimise your project, such as by reducing the download size and memory use as much as possible. This tutorial covers exactly what Construct is doing on export, as well as how the export settings affect it, and finishes with some time-saving tips.

Step 1: image deduplication

It's relatively common that projects contain duplicate images. For example you may have cloned an entire object type, or have an animation which re-uses the same frame in several places (e.g. in A B A C A D form). In this case there may be duplicate image files used in the project.

To ensure previews are fast, duplicate images are not removed when previewing. However when exporting, Construct looks for and removes duplicate images. This helps reduce the download size and memory use, since there's no point having identical images downloaded twice or loaded in to memory twice.

Note the size of images is still taken in to account: a 10x10 solid black image is considered different to a 11x11 solid black image, because it cannot be guaranteed that the project will look and behave identically if one was removed in favour of the other.

Step 2: spritesheeting

Images are stored in the project in separate files. For example a Sprite with 10 animation frames will have 10 separate image files in the project folder. If animations were also exported like this, it could cause a few problems. Each image has to be downloaded separately in browser games, so this will mean 10 separate HTTP requests, and each HTTP request has a certain amount of extra overhead. Sprites often have animation frames with lots of similar parts, and this image data will be duplicated in each animation frame file. Additionally in some cases images must be placed on a power-of-two size surface (e.g. 128x128, 256x256, 512x512 etc), which can make them use more memory.

Spritesheeting is the process of making a single large image with lots of animation frames on it. It solves all these problems: there are fewer HTTP requests in browser games; the PNG or JPEG compression can eliminate similar parts of the images across animation frames, making the download smaller; and Construct always uses a power-of-two size sprite sheet, minimising any wasted memory. Here's what a spritesheet for the player's ship in Space Blaster looks like:

An example spritesheetAn example spritesheet

The combined spritesheets for this single object is a 300kb download and uses 2mb of memory. Without spritesheets the separate images would have been a 460kb download and used about 3mb of memory. So when applied to the entire project the savings can be quite significant.

In Construct 3, spritesheets are generated in the editor when you open the project. This allows preview mode to take advantage of the benefits of spritesheets as well. When you export your project, you may notice that you get a set of spritesheet images instead of lots of individual image files.

Construct's priority is to minimise memory use at runtime. To this end Construct may opt to export two or three spritesheets of a smaller size if the images can fit. For example if the images fit across two or three 512x512 spritesheets, it will export that instead of a single 1024x1024 spritesheet, since it uses less memory. In some cases this can actually make the download slightly larger - there is a little bit more redundant image data saved. However it is usually more important to minimise memory use than save a few percent more on the download size.

For compatibility with the broadest range of hardware, there's a maximum spritesheet size of 2048x2048. You should also avoid using images over about 1000x1000 since they are very wasteful of memory and will be awkward to fit in to spritesheets. If Construct cannot fit an image on a spritesheet, it just exports it as its own file again, missing out on the benefits of spritesheeting. Also, to avoid adjacent image's colors "bleeding" or "fringing" across to other frames, Construct leaves a 1 pixel space between all frames on a spritesheet. This means it won't be able to fit four 128x128 images in a single 256x256 spritesheet, so try to ensure Sprite images are just below a power-of-two size. The optimal size is two pixels less than a power-of-two size, e.g. 30x30, 126x126 or 254x254. (Note however that Tiled Background objects do work best at exactly a power-of-two size.)

Note that if you set the Downscaling project property to High quality, images on spritesheets are always padded out to power-of-two sizes in order to mitigate two minor rendering issues. This negates the memory saving of spritesheets and so should not be used without reason. For more information see Memory usage.

Step 3: image recompression

When exporting spritesheets, Construct also tries to make the download as small as possible. This is by far the most intensive step, and will usually take the majority of the export time.

First of all, Construct respects the format you've set for any images in the Image Format dialog in the Animations Editor. All images are stored in the project as lossless PNG-32 files to prevent degradation while editing. If any images are set to use JPEG format, they are recompressed at this point. This is a lossy (quality-degrading) operation if you have chosen JPEG. Note this means there is no point importing JPEG files to Construct itself - Construct will still simply convert any imported images to PNG-32, and wait until export to recompress it to your desired format set in the Image Format dialog. Therefore prevent unnecessary degradation of image quality, only ever import PNG-32 images to Construct, and set the intended format in the Image Format dialog.

Also note images are fully decompressed before rendering at runtime, so the file format will have no effect on memory use - only the download size. However note it's often important to choose the JPEG format for any large, detailed scenery images, since it can make the download considerably smaller. Be warned that JPEG does not support transparency - if any parts of an image set to use JPEG are transparent, the transparent parts will turn opaque black.

Next, all PNG images are run through a tool called OptiPNG, which tries lots of different ways to compress the image and picks whichever results in the smallest file size. This often gets an automatic and lossless 10-15% saving on the download size, but can take a long time. It's also able to losslessly palette-reduce 32-bit PNGs to 8-bit PNGs when the image has 256 colors or fewer, resulting in a much smaller file size, which is particularly effective for art styles which don't use many colors, like retro style pixel art. If you turn off the image recompression option on export, this step is skipped. This can make exports very quick, but can also make the download size significantly larger.

The image recompression process is relatively sophisticated. It is also totally lossless (preserving the image quality exactly) unless you explicitly set a lossy format in the Image Format dialog. As a result, usually there is nothing to be gained by using other image compression tools or services after export; you can trust Construct to do an excellent job of compression by itself upon export. (And as before, there is nothing at all to be gained from using such tools when importing to the Construct editor, since it immediately converts them to PNG-32 and you might have unnecessarily degraded the quality of your images.)

Step 4: script minification

Finally, the resulting javascript code is minified. This renames everything possible in the JavaScript code to use the shortest names possible, which makes the script smaller and quicker to download. It also has the nice side effect of making it incredibly difficult to reverse-engineer the exported project, since what were previously useful terms in the script become nonsense. It may also make the resulting JavaScript slightly more efficient, since it employs some basic optimisations.

In some rare cases, especially with third party plugins, minifying can cause bugs. The option to turn it off is mainly there as a diagnostic to help resolve such issues. You should always enable minification, unless you are investigating a bug.

Omission of audio files

Construct 3 uses WebM Opus to support audio playback across all platforms. However for compatibility with older browsers you may need to use additional audio formats like MP3 or MPEG-4 AAC (.m4a). See the Import Audio dialog manual entry for more information.

Construct knows in advance which audio formats are needed for which exporters. If possible, Construct will omit audio files that are known to be unnecessary. For example Android can play WebM Opus audio, so if you have your sounds in both WebM Opus format and MPEG-4 AAC format, Construct will ignore the MPEG-4 AAC audio and only export WebM Opus. On the other hand the HTML5 exporter has to include all files, since it can run on pretty much any platform.

In short, you should never need to manually delete audio files before exporting your project - Construct will automatically omit any files that are definitely unnecessary for the chosen platform.

Multi-core processing

The spritesheeting, deduplication and recompression steps are processed on all available CPU cores to speed up the export. For example on a quad-core machine Construct 3 will be able to recompress four images at a time in parallel, making that step four times faster. If you find exporting is taking a long time and you're looking to buy a new computer, find one with lots of CPU cores!

Conclusion

Construct does a lot of work for you on export. The key lessons are:

  • Don't worry about having duplicate images - they're automatically removed.
  • The image format (e.g. PNG-, JPEG) only affects the download size, not the runtime memory use.
  • If possible make sprite images just under a power-of-two size, so they can pack in to spritesheets efficiently. However try to make Tiled Backgrounds exactly power-of-two sized.
  • Don't import lossy image files (e.g. PNG-8 or JPEG) in to Construct. They are always stored as lossless PNG-32 until you export, at which point it respects what you've set in the Image Format dialog.
  • Don't worry about the fact Construct splits up spritesheets in to separate files when you import them to the editor. It will re-spritesheet them in a memory-efficient way.
  • Don't bother trying to run the exported image files through other compression tools or services. Construct is probably already doing a very good job.
  • Don't try to manually delete audio files before exporting. Construct automatically removes any that are definitely not needed on export.
  • If exporting is slow, try getting a machine with more CPU cores!

Knowing what Construct does for you at export can help you work effectively with Construct and avoid any unnecessary work.

Next Tutorial In Course

Checking for errors in browsers 02:53

This tutorial covers using your browser's console for errors in your Construct games. It also includes helpful links for mobile app debugging.

  • 3 Comments

  • Order by
Want to leave a comment? Login or Register an account!
  • I understood a lot. good tutorial.

  • From what I can see, none of the image optimisations apply to images stored in the project files folder, is this correct? I have to use the project file folder in the absence of a 3D object "set face to use image of (by name)" action

      • [-] [+]
      • 1
      • Ashley's avatar
      • Ashley
      • Construct Team Founder
      • 1 points
      • (0 children)

      That's right, images added as project files are just copied to the export as-is and aren't processed any further.