Skip to content

Mastering Asset Packing

In Roblox, image performance is primarily a battle against draw calls. If your UI uses 50 individual images, the engine treats them as 50 separate tasks to load and render. By consolidating these into a single spritesheet, you allow the engine to process everything in a single pass—effectively slashing 50 draw calls down to just one.

In this guide, we’ll walk through how Tungsten automates the complex math of packing images and generates the code needed to use them.

To pack assets, Tungsten needs to know which files belong together. The cleanest way to do this is by organizing your assets/ folder.

Let’s say you have a set of UI icons. Arrange them like this:

  • Directoryassets/
    • Directoryicons/
      • home.png
      • settings.png
      • user.png
      • menu.png

By default, Tungsten syncs files individually. To bundle them into a spritesheet, you need to define a [inputs] entry in your tungsten.toml.

Open your configuration file and add the following:

[inputs.ui_icons]
path = "assets/icons/*.png"
output_path = "IconSheet.luau"
packable = true
  • path: A glob pattern defining which images Tungsten should combine.
  • output_path: The file path where Tungsten will generate the Luau module containing your asset references.
  • packable: A boolean flag that explicitly enables the spritesheet packing logic for this group.

Run your sync command just like you did in the first tutorial:

tungsten sync cloud

When Tungsten runs, it detects the input from your configuration and performs the following:

  1. It locates all images matching your path glob pattern.

  2. It computes the most efficient layout for your assets on a single canvas.

  3. It creates the optimized spritesheet image and the output_path Luau module.

  4. It pushes the spritesheet to Roblox.

  5. It refreshes your code generation file with the correct coordinates.

Because Tungsten generates type-safe code, you don’t need to manually calculate the ImageRectOffset or ImageRectSize for every image.

Once the sync is complete, simply require the generated module in your scripts:

local Assets = game.ReplicatedStorage.Assets

-- Require the module Tungsten generated
local Icons = require(Assets.IconSheet)

local home = script.Parent

-- Apply the sprite properties automatically
home.Image = Icons.home.Image
home.ImageRectOffset = Icons.home.ImageRectOffset
home.ImageRectSize = Icons.home.ImageRectSize

Tungsten handles the “boring” math of sprite coordinates, so you can simply point your ImageLabel to the asset reference generated by the tool.