Boosting Unity Game Performance: Sprite Sheet Optimization

Joachim Grill, Andreas Loew
Last updated:
Boosting Unity Game Performance: Sprite Sheet Optimization

This tutorial shows you how to use TexturePacker to create optimized sprite sheets for Unity's 2D system.

You'll learn how to:

  • Prepare your Unity project to read TexturePacker sprite sheets
  • Create your sprite sheet and load it into Unity
  • Handle sprite updates and changes in Unity
  • Streamline your sprite workflow in Unity

Why you should use optimized sprites

You probably already know that sprite sheets increase your game's performance. TexturePacker takes this optimization even further.

Unity creates sprite meshes automatically — these reduce overdraw by not rendering transparent pixels. However, Unity's mesh generation algorithm has limitations:

Sprite polygon quality in Unity and TexturePacker
TexturePacker reduces the number of triangles and overdraw compared to Unity's internal mesh algorithm

TexturePacker comes with a new algorithm to create better meshes. As you see above:

  • Triangle count reduced by 69% — freeing up CPU resources
  • Overdraw reduced by 30% — freeing up GPU resources

What you are going to learn in this tutorial

TexturePacker, together with the free TexturePacker Importer, creates sprite sheet assets that can be directly used from Unity's graphical editor or through scripts.

Sprites are accessible through Unity's standard API using the Sprite class — no additional runtime code required! The sprite sheets also work with Unity's UI classes.

This is what you get:

  • Increased performance through optimized sprite meshes
  • Easy sprite management
  • 1-click import/export
  • No additional runtime code or library required
  • Fully automated slicing of sprites
  • Reducing Draw Calls in Unity
  • Saves you lot of time

Creating sprite sheets

Start by downloading TexturePacker from here:

It's available for Windows, macOS and Linux. You can use the free trial for this tutorial. Yes, TexturePacker costs a bit of money, but it's a perpetual license (no subscription!) that comes at a very affordable price. We also support independent developers with a big discount.

To create a new sprite sheet, simply start TexturePacker and drag & drop the directories containing your sprites to the Sprites area. TexturePacker preserves the directory structure under the directory you added - allowing you to group and sort sprites. New sprites in the directory are added to the sheet as soon as you re-enter TexturePacker.

TexturePacker: Add sprites

Select Unity - Texture2D as Data format in the settings on the right side.

Click on the folder icon next to Data file and choose a location in the Assets directory of your Unity project — the TexturePackerImporter script will re-import the sprite sheet into your project each time you publish an updated sheet with TexturePacker.

TexturePacker distinguishes between the Trim Mode and the Algorithm used for packing the sprite sheet.

  • Trim Mode: The default for Unity is Polygon outline. This creates a tightly fitting polygon around each sprite, which reduces overdraw and improves rendering performance.
  • Algorithm: The default packing algorithm is set to Polygon. With this setting, the packer uses each sprite’s polygon outline to arrange them efficiently, resulting in a compact sprite sheet that saves both disk space and runtime memory.

This configuration is generally the best choice for sprites. It also works well with UI.Image but there you have to set property useSpriteMesh to true. Alternatively you can choose the MaxRects algorithm for packing.

Polygon packing is a complex process and takes some time. You can speed up things in two ways:

  • Increase the Tracer Tolerance — this will create less complex polygons
  • Use algorithm MaxRects — TexturePacker uses rectangles for packing but still uses the optimized meshes for rendering

Finally, press Publish to create the sprite sheet.

Optimizing polygon meshes

You can influence the quality of the meshes using Tracer Tolerance. A higher tolerance results in less vertices but more overdraw.

The best value for your project depends on two factors: Your CPU usage and GPU usage. Each vertex requires CPU power for the calculation. On the other hand: Each additional pixel adds work load on the GPU.

If your project is high on computation (CPU) but you still have some resources on the GPU side go for a lower vertex count

  • increase tracer tolerance.

If your project is high on graphics (GPU) but you still have some resources on the CPU side go for a lower overdraw

  • reduce tracer tolerance.

Keep an eye on the values TexturePacker is displaying at the bottom of the sprite sheet. In the following example you see that decreasing the overdraw by additional 2% comes with more than duplicating the vertex count.

Tracer tolerance setting: Triangle count vs overdraw
Adjust the tracer tolerance to strike a balance between the number of vertices and the required area

Using sprite sheets

To enable the import of TexturePacker sprite sheets in Unity, you have to install the TexturePacker Importer plugin, which you can download from the Unity Asset Store for free: TexturePacker Importer

The script extends Unity to read sprite sheet data created with TexturePacker and to automatically create native Unity assets which you can use with the Unity Editor. The code of the script only runs during development. It does not become part of your product or game.

Download TexturePacker Importer for Unity from the Asset Store
Download the TexturePacker Importer from the Asset Store

The plugin comes with some demo assets — but it's perfect if you only install the Editor folder and its content. Don't rename this folder, because this name ensures that it is automatically loaded by the Unity Editor.

The TexturePackerImporter checks for each texture file if a corresponding .tpsheet file exists. This is the data file written by TexturePacker — it is used by the Unity importer to slice the texture into individual sprites.

The assets and sprite sheets are automatically updated in Unity when changes are found. No manual intervention required!

Use the symbol next to the texture asset to display the individual sprites. To create an animation simply select the frames and drag them onto the scene.

Unity Assets folder structure

Now you can use your sprites as usual, directly from the editor.

You can, of course, also access the sprite through the scripting API:

Enhancing Unity's Render Performance by Minimizing Draw Calls

The efficiency of your game's rendering performance largely depends on the quantity of draw calls required to render a scene. The ability to process more draw calls in a batch results in a noticeable performance boost.

When individual sprites or UI images are added to a scene, each creates a separate draw call, which is not optimal for performance:

This is bad: Adding single sprites increases the number of draw calls
This is bad: Adding single sprites increases the number of draw calls

Alternatively, rendering using a sprite sheet created with TexturePacker significantly optimizes this process by batch rendering. Consequently, the number of draw calls is dramatically reduced to just one:

This is good: Using sprites reduces draw calls by batching the rendering of the sprites
This is good: Using sprites reduces draw calls by batching the rendering of the sprites. Note that TexturePacker also decreased the number of Triangles (Tris) and Vertices (Verts)

Worth noting is TexturePacker's ability to decrease the number of triangles and vertices (in this example, a tracer tolerance of 600 was used).

  • Without TexturePacker: Unity has 138 triangles, 154 vertices
  • With TexturePacker: Reduced to 74 triangles, 94 vertices

This gives you full control over the rendering process.

Pivot point editor

TexturePacker contains an easy to use pivot point editor with real time animation preview.

Select your sprites in the left panel and click on Sprite settings in the top toolbar. Pivot points are represented by a circle. You can select multiple shapes and move all pivot points at once.

Edit your sprite's pivot points while observing the changes in the animation preview window
Edit your sprite's pivot points while observing the changes in the animation preview window

Use Preview Anims from the top toolbar to see an animation of the selected sprites. Changes to the pivot points are updated while you edit them.

The right panel contains edits to set the pivot points in absolute and relative coordinates. The relative coordinates use the range of 0 — 1 where 0/0 is in the bottom left of the sprite.

The Predefined combo-box let you choose from the standard positions in the corners and center of the sprite.

You can also set the default values for new sprites by clicking the arrow button on the right panel.

Border editor (9-patch, 3-patch)

TexturePacker also supports editing of sprite borders — also know as 9-patch or 3-patch sprites.

You can use this feature to create scalable buttons, bars and other objects with a defined stretch.

A sprite is cut into 3 (x or y direction) or 9 parts (x and y direction). The parts of the sprite in the corners are fixed. The others stretch when the sprite is resized.

You can enable the border setting for individual sprites from the Sprite settings in the top toolbar.

Drag the green lines to separate the 9 segments for a 9-patch sprite. Move the unused lines to the top/bottom or left/right to create 3-patch sprites.

Enabling Mesh rendering in Unity UI

The UI classes of Unity ignore the polygon mesh information by default and simply use rectangular sprites. The result is that you can see some artifacts from other sprites with polygon packing enabled.

The simple solution to get rid of these artifacts is to set useSpriteMesh to true.

Updating pivot points and sizes in UI Image objects

Unity automatically copies parts of the sprite properties into the UI image on creation. The problem is that Unity does not copy all values — and even worse — it does not update the values when the sprite details like pivot point or size change.

We've added a small tool that helps you update the UI Image objects. You can find it in the UI context menu. It's called Set Native Size + Pivot :

Apply pivot points and sizes to Unity UI Image
Updating pivot points and image sizes in UI.Image in Unity

How can I access a sprite on a sprite sheet from code?

If you place a sprite on a sprite sheet, it cannot be loaded separately like Resources.Load<Sprite>("sprite01"). One advantage of a sprite sheet is to improve speed by loading all sprites in a bunch instead of reading each file separately. So calling Resources.LoadAll<Sprite>("my_spritesheet") is the right way to load the sprite sheet file and get access to all sprites which are on it.

It's a deficiency of the Unity API that Resources.LoadAll<Sprite> returns an array instead of a dictionary. So you have to iterate over the Sprite[] and compare the sprite names to find a specific sprite.

The even better solution might be to construct a dictionary yourself:

Sprite[] sprites = Resources.LoadAll<Sprite>("my_spritesheet");
Dictionary<string, Sprite> spritesDict = new Dictionary<string, Sprite>();

foreach (Sprite sprite in sprites)
{
    spritesDict[sprite.name] = sprite;
}

...

sprite1 = spritesDict["sprite01"];

Please keep in mind that you have to place your sprite sheet in a Resources folder to be able to load it with the methods of the Resources class. For details have look in Unity's Resources documentation.

Load sprite sheets from AssetBundles

In Unity an AssetBundle is an archive file containing assets which can be loaded at runtime. If you have added sprite sheets to Asset Bundles you can load them in this way:

AssetBundle bundle = AssetBundle.LoadFromFile("Assets/AssetBundles/MyBundle");
if (bundle != null)
{
    Sprite[] sprites = bundle.LoadAssetWithSubAssets<Sprite>("MySpriteSheet");
    ...
}

To access the sprites by name you can use a dictionary as explained in the previous section.

Summary

TexturePacker simplifies the workflow for your sprites in Unity - automating the whole process.

Changing your sprites is quite simple:

  • Save the new sprites in your assets folder
  • Press Publish in TexturePacker
  • Switch to Unity and use your sprites

Using the sprite sheets reduced the draw calls and might help increase the performance of your game.