One of the most annoying parts of modding 2D games — especially tile-based ones — is dealing with spritesheets and texture atlases.

If you’ve modded Prison Architect, RimWorld, or similar games, you’ve probably had to:

  • Cram your sprites into a shared PNG file
  • Copy paste into exact pixel-aligned grid slots
  • Maintain an accompanying XML or Lua file with offsets, pivots, and sizes
  • Rebuild everything if just one image changed

It’s tedious, error-prone, and downright unfriendly for casual modders.

That’s why my engine does something different.

The Problem Naked

Rendering many small images efficiently in modern graphics APIs (DirectX/OpenGL) requires batched textures, i.e., texture atlases. You can’t just bind 300 different .png files every frame — that would tank performance.

So engines usually require modders to:

  • Pre-combine all their images into a large atlas
  • Manually specify where each sprite lives (pixel offsets, size, etc.)

But this is a bad experience:

  • Hard to edit or iterate on
  • Conflicts easily with other mods (shared atlases)
  • Non-technical modders can’t deal with texture packing tools

The Solution: Dynamic Atlas Builder

In my engine, modders don’t build texture atlases at all.

Instead, each mod:

  • Just drops in individual PNG files — one per sprite
  • Registers them with naming conventions (like ModName/wall_brick_side.png)
  • Doesn’t need to worry about dimensions, grouping, or ordering

At startup, my engine:

  • Loads all sprite files from all active mods
  • Compares the files metadata with the cached ones
  • If anything has changed, automatically builds a shared texture atlas
  • Records where each sprite was packed (UVs, size, pivot, etc.)
  • Caches the result to disk (so it’s rebuilt only if assets change)

Little Tech Talk

Under the hood, it uses SkiaSharp library to decode .png files, and RectSharp for rectangle packing algorithm implementation.

But the real point of my pride is that this system is implemented in my engine as a plugin. It fits into my vision of the game engine to be truly extensible.

Even such the crucial low-level component can potentially be replaced or extended by a C# modder if they really want custom packing strategies (e.g. for performance tuning).

Why this matters

For modders, this means:

  • No texture packing tools required
  • No fiddling with sprite sheets
  • No sprite collisions with other mods
  • Easy to add or replace one image at a time

You can just treat sprites as standalone assets, and the engine takes care of efficient batching under the hood.

And for performance? It’s just as fast as a hand-packed atlas — because after startup, it is a real atlas. (You can even locate it in your app data folder as a normal .png file!) It’s just built for you automatically.

This is one of those invisible systems that no one notices when it works — but it turns modding from a chore into a pleasure.

And that’s the goal.