Mini Tutorial: How to batch replace textures with different file formats in Unity?

In relation to my previous tutorial: Mini Tutorial: How to batch convert image files to PVR (for iPhone app development)?

So you have a Unity project that was previously not planned for iOS (for PC, Mac or web or whatever), and you might not be as conscious of the texture file formats (iOS is probably the only one with so many constraints).

According to Unity’s User Manual:

Use iOS native PVRT compression formats. They will not only decrease the size of your textures (resulting in faster load times and smaller memory footprint), but also can dramatically increase your rendering performance! Compressed texture requires only a fraction of memory bandwidth compared to full blown 32bit RGBA textures.

So after converting all my textures (or creating a copy of my textures in .pvr format using Automator), I’m supposed to change all the material textures in my Unity Project and that’s a lot. So I wrote this tiny Editor script to do that for me. It will even delete the old texture (.tga or .png or whatever) from the Assets folder.

So here it is:

using UnityEngine;
using System.Collections;
using UnityEditor;                      
 
public class ChangeTexturesToPVR : ScriptableWizard
{
     [MenuItem (“Project Tools/Change Textures to PVR”)]
    static void MakeFolder ()
    {   ChangeTextures();
    }
 
    static void ChangeTextures()
    {
        string filePath = AssetDatabase.GetAssetPath(Selection.activeGameObject);
        int index = filePath.LastIndexOf(“/”)+1;
        filePath = filePath.Remove(index);
        
        foreach (Transform child in Selection.activeGameObject.transform)
        {    Material[] mats = child.renderer.sharedMaterials;
           
            foreach(Material mat in mats)
            {    string texFilePath = filePath;
                texFilePath = texFilePath.Insert(texFilePath.Length, “Texture/”);
                if(mat.mainTexture != null)
                    texFilePath = texFilePath.Insert(texFilePath.Length, mat.mainTexture.name);
               
                string oldTexFilePath = texFilePath;
                oldTexFilePath = oldTexFilePath.Insert(oldTexFilePath.Length, “.tga”);
               
                texFilePath = texFilePath.Insert(texFilePath.Length, “.pvr”);
               
                mat.mainTexture = (Texture)AssetDatabase.LoadAssetAtPath(texFilePath, typeof(Texture));
                AssetDatabase.DeleteAsset(oldTexFilePath);
            }
        }
       
       
    }
}

If your old textures are in “.png”, just change “.tga” in the code above to well, “.png”.

Select the model (.fbx or .obj file) whose materials and textures that you would want to change.

And then go to the menu and click Project Tools > Change Textures to PVR (yes, I created a Menu item for it).

And then voila!

UPDATE:

I edited the code a bit:

using UnityEngine;
using System.Collections;
using UnityEditor;                     

public class ChangeMaterialTexturesToPVR : ScriptableWizard
{
     [MenuItem (“Project Tools/Change Material Textures to PVR”)]
    static void MakeFolder ()
    {   ChangeTextures();
    }

    static void ChangeTextures()
    {
        for(int i=0; i < Selection.gameObjects.Length; i++)
        {    if(Selection.gameObjects[i].transform.childCount == 0)
            {    changeTexture(Selection.gameObjects[i].transform);
            }
            else
            {    foreach (Transform child in Selection.gameObjects[i].transform)
                {    changeTexture(child);   
                }
            }
        }
    }

    static void changeTexture(Transform obj)
    {   
        if(obj.renderer)
        {    Material[] mats = obj.renderer.sharedMaterials;

            foreach(Material mat in mats)
            {   
                string texFilePath = “”;

                if(mat.mainTexture != null)
                {    texFilePath = AssetDatabase.GetAssetPath(mat.mainTexture);

                    if(!texFilePath.Contains(“.pvr”))
                    {    texFilePath = texFilePath.Remove(texFilePath.IndexOf(“.”));

                        string oldTexFilePath = texFilePath;
                        oldTexFilePath = oldTexFilePath.Insert(oldTexFilePath.Length, “.tga”);

                        texFilePath = texFilePath.Insert(texFilePath.Length, “.pvr”);

                        Texture tex = (Texture)AssetDatabase.LoadAssetAtPath(texFilePath, typeof(Texture));

                        if(tex != null)
                        {    mat.mainTexture = tex;
                            AssetDatabase.DeleteAsset(oldTexFilePath);

                            Debug.Log(texFilePath);
                        }    else
                        {    tex = (Texture)AssetDatabase.LoadAssetAtPath(oldTexFilePath, typeof(Texture));
                            mat.mainTexture = tex;

                            //Debug.Log(oldTexFilePath);
                        }
                    }
                }
            }

            obj.renderer.sharedMaterials = mats;
        }
    }
}

Now, all you have to make sure is that the .pvr and the .tga (you can change this to .png or .tif or .whatever), is in the same folder and that’s it.

That’s about it.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s