Friday 6 January 2017

Unity sprite packer and texture post processing

I'm currently playing around with some 2D assets in Unity and I found one of particular interest. I'll try to build a small mobile game to release on the blog perhaps.

While testing scenes and importing assets I came across a problem I never encountered before: in the downloadable package all the sprites are not packed in a single sprite sheet, as it is often the case, rather, they are all single, separated files. This really is not a big issue, however, I always like to find the best approach to solve problems and I came up with an unusual solution,

The first thing that came to mind was to download Texture Packer and pack all the sprites in different spritesheets (player, enemy, tileset,ecc.). The second option was to use the build-in-Unity feature Sprite Packer. Since I wanted to try something new, I opted for the latter.

If you are not familiar with the feature, this window will let you pack sprites into spritesheet in order to reduce draw calls and improve performance. In order to do so, we have to give a tag to each texture imported from the package. (Fig 1).

Fig 1
We can then go to Window->Sprite Packer and press the Pack button on the top right corner of the window. At this point Unity will create a sprite-sheet for each tag with all the textures with that particular tag. Simple enough. (Fig. 2).



However, the problem came when I realized I had quite a lot of texture assets to set up in order to achieve this. In addition, for each asset file of this type I needed to change some other parameters, like Filter Mode, MipMap, ecc.

The idea of having to do that manually for each texture was not really thrilling and, moreover, I would need to remember to do so for any additional asset of type texture I might import later while developing the project. Basically, I needed some other way to achieve this automatically.

So, after some research, I came across something called AssetPostProcessor.

This class, and I'm quoting the Unity documentation here, "lets you hook into the import pipeline and run scripts prior or after importing assets".

I can now write a very simple script that changes all the parameters I need to change for each texture imported without having to touch any of the asset files.

The sprite processor script

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public class SpriteProcessor : AssetPostprocessor {

 void OnPostprocessTexture(Texture2D texture)
 {
  

  TextureImporter importer = (TextureImporter)assetImporter;

  importer.filterMode = FilterMode.Point;
  importer.maxTextureSize = 64;
  importer.spritePixelsPerUnit = 16;
  importer.mipmapEnabled = false;


  DirectoryInfo parent = Directory.GetParent (importer.assetPath);

  importer.spritePackingTag = parent.Name;


 }
}

Amazingly, the script needed is in fact very simple.

First thing, we need to extend the class AssetPostprocessor.

The code will need to run within the method OnPostprocessTexture, which will run for every single asset file of type texture once it has been imported in the engine.

We can then grab the TextureImporter object and apply our changes to the files. See how I modified some parameters and I assigned the name of the parent folder of the texture file as a packing tag (line 17). This way, for each folder containing textures for a particular animation we will have a sprite-sheet.

Project folder
Inspector

If we pack now all the sprites, we can see we will have many sprite-sheets, one for each folder with all the sprites in it.


Conclusion

Creating tools to help yourself developing the game is the best way to improve your workflow. With this simple script I no longer have to worry about imported textures,knowing that everything is being taken care of in the post processing.. Much more can be done using this class, of course, it always depends on the project and what particular tools can help you creating your game.