Sponsored By

Importing Textures Into Unity

Where we take a gander at customizing the texture import process somewhat to make it easier to control.

Amir Barak, Blogger

May 19, 2014

5 Min Read
Game Developer logo in a gray background | Game Developer

I'm usually better at the whole pun for title thing, honest.

Importing textures into Unity is usually a fairly simple process involving the following steps;

  • Copy image into assets folder.

  • Update import settings.

  • Apply import settings.

  • Rinse/Repeat.

Yup, no problems there. Except that the projects I'm currently working on have A LOT of textures. And you know what, even if they didn't, I'm lazy. I can't stand manually doing something which can be automated. Oops, gave away the rest of the post. Let's automate.

Disclaimer; the system I'm actually using has evolved from this simple concept and is not presented here. The core idea though is the same.

First though let's address the question burning in everyone's mind. Amir, why do you even want to automate it?? That's just crazy!

Well, yeah, sort of. But not all textures should be treated the same, meaning not all textures require the same import values. And that means that unless we have a mechanism for grouping images we're going to have to remember to update everything and every time we bring in a new file. And for me, that way lies madness.

Secondly, how do we group textures?

I'm glad you asked. At the moment, by folders. This way we can have a folder for mipmapped textures and a folder for sprite textures and a folder for whatever-we-want-textures. Our puzzle is made of the following pieces; the asset post processor, a simple MonoBehaviour script attached to a prefab and a custom inspector.

Let's get to some code!

We'll start from the simplest piece. The TextureProcessingFolders component [MonoBehavior]. This component is a simple string container for holding directories.

public class TextureProcessingFolders
  : MonoBehaviour
{
    public List<string> Folders;
}

 

The next step is to create a prefab and add this script to it. Save the prefab to a known location so we can later load and use it. The reason I've gone with this approach rather than some custom made XML or JSON or whatever script is twofold. First Unity already gives us simple serialization for free using components/prefabs and secondly, it's easier to use Unity's native inspector capabilities to manipulate the string list during editing. Okay, now we have our prefab and the behaviour it's time to add a custom inspector.

But wait! Why do we even need a custom inspector? Unity will automatically create an inspection view of the component and we can just add directory strings manually. You may have guessed the answer by the usage of the word manually. If I wanted to do things manually I'd go build a lego house (I do love playing with Lego by the way but that's another story). The goal of our custom inspector then is to allow dragging folders and automatically setting their path into our list.

Here's the code. Bit cute if I do say so myself.

[CustomEditor(typeof(TextureProcessingFolders))]
public class TextureProcessingInspector
  : UnityEditor.Editor
{
    public override void OnInspectorGUI()
    {
      var processing = (TextureProcessingFolders) targets;
      var dragged = EditorGUILayout.ObjectField("Folder", null, typeof(Object), false);
      if (dragged == null)
        return;

      var path = AssetDatabase.GetAssetPath(dragged);
      if (!processing.Folders.Contains(relative_folder)
        processing.Folders.Add(path);
    }
}

 

As you can see we're using Unity's own object inspection field to allow retrieving dragged asset paths. I've not added in but there should be checks to make sure that the dragged object is actually a directory and all that jazz.

This post is dragging a bit as well but it's nearly over so I'll let it slip. The last piece of the puzzle comes in the form of the asset post processor.

public class TextureProcessor
  : AssetPostprocessor
{
  public void OnPreprocessTexture()
  {
    var prefab = AssetReader.Get<gameobject>(prefab_path);
    var processing = prefab.GetComponent<textureprocessingfolders>();
    var asset_path = Path.GetDirectoryName(assetPath);
    var process_asset = processing.Folders.Any(asset_path.Contains);
    if (!process_asset)
      return;

     var settings = new TextureImporterSettings
       {
         mipmapEnabled = false,
         wrapMode = TextureWrapMode.Clamp,
         textureFormat = TextureImporterFormat.RGBA32,
         maxTextureSize = 2048,
         alphaIsTransparency = true,
       };

    var importer = (TextureImporter) assetImporter;
    importer.SetTextureSettings(settings);
  }

 

Ah, I love Unity's solid API. Let's just take a moment to appreciate the fact the we're inherting from the Post processor in order to use its Pre processing method.

Well, that's it. No more. Any thoughts whether this is useful and how to extend it into a more robust system?

 "I think of flying down into a sea of pens and feathers; and all other instruments of faith and sex and God"

Read more about:

Featured Blogs

About the Author

Daily news, dev blogs, and stories from Game Developer straight to your inbox

You May Also Like