Tutorials

Editor folder contains any editor scripts. It allows no mono behavior scripts in it.

AssetPostprocessor is one of the editor class. One of the properties is assetPath, the path name of the asset being imported.

A series of function is called in the following order during the model import:

  1. OnPreprocessModel: I can override ModelImporter settings in here.
  2. After meshes and materials are imported, GameObjects hierarchy is created from the imported nodes. Use OnPostProcessMeshHierarchy to change the hierarchy. Every GameObject that represents an imported node is given a corresponding MeshFilter, MeshRenderer, and MeshCollider component. OnAssignMaterialModel is invoked before assigning a Material to the MeshRenderer.
  3. After MeshRenderers and “userdata” exists, and before children game objects are generated, OnPostprocessGameObjectWithUserProperties is called
  4. if animation generation was not disabled at previous stages, SkinnedMesh and Animations are generated. Avatar is also created and GameObjects hierarchy is optimized if possible. Then OnPostprocessModel is called for the root GameObject.

Code example: change texture type to “Sprite” when a new texture is imported to the “Sprites” folder.

using UnityEditor;
using UnityEngine;

public class SpriteProcessor : AssetPostprocessor
{
    private void OnPostprocessTexture(Texture2D texture)
    {
        string lowerCaseAssetPath = assetPath.ToLower();
				
				 // check if it's in sprites directory
        bool isInSpirtesDirectory = lowerCaseAssetPath.IndexOf("/sprites/") != -1;

        if (isInSpirtesDirectory)
        {
            TextureImporter textureImporter = (TextureImporter) assetImporter;
            textureImporter.textureType = TextureImporterType.Sprite;
        }
    }
}

ScriptableWizard

It’s to create an editor wizard. Editor wizards are typically opened using a menu item.

using UnityEngine;
using System.Collections;
using UnityEditor;

public class SelectAllOfTag : ScriptableWizard 
{

    public string searchTag = "Your tag here";

    [MenuItem ("My Tools/Select All Of Tag...")]
    static void SelectAllOfTagWizard()
    {
        ScriptableWizard.DisplayWizard<SelectAllOfTag> ("Select All Of Tag...", "Make Selection");
    }

    void OnWizardCreate()
    {
        GameObject[] gameObjects = GameObject.FindGameObjectsWithTag (searchTag);
        Selection.objects = gameObjects;
    }
}

ScriptabelWizard has 3 messages: OnWizardCreate is called when the Create button is clicked. OnWizardOtherButton is called when the other button is lcicked. OnWizardUpdate is called when the wizard is opened or user changed something in the wizard.

Source:

  1. YouTube: Live Training 3rd October 2016 - Creating Basic Editor Tools
  2. Unity Documentation: AssetPostprocessor
  3. Unity Documentation: ScriptableWizard

My Application

Q: A batch of texture’s format was set wrong, especially the max size and compression.

A: Apply AssetPostprocessor to change the current setting when reimporting.

public class TextureFormatReimporter : AssetPostprocessor
{
    private static string mainPath = "assets/textures/path";

    void OnPreprocessTexture()
    {
        string lowerCasePat = assetPath.ToLower();
        if (lowerCasePat.Contains(mainPath))
        {
            TextureImporter texImporter = (TextureImporter)assetImporter;
            
            if (/*in some condition*/)
            {
                texImporter.isReadable = false;
            }

            texImporter.mipmapEnabled = false;

            TextureImporterPlatformSettings defaultSetting = texImporter.GetDefaultPlatformTextureSettings();
            TextureImporterPlatformSettings standAloneSetting = texImporter.GetPlatformTextureSettings("Standalone");
            TextureImporterPlatformSettings iOSSetting = texImporter.GetPlatformTextureSettings("iPhone");
            TextureImporterPlatformSettings androidSetting = texImporter.GetPlatformTextureSettings("Android");

            if (androidSetting.overridden)
            {
                defaultSetting.maxTextureSize = androidSetting.maxTextureSize;
            }
            else if (iOSSetting.overridden)
            {
                defaultSetting.maxTextureSize = iOSSetting.maxTextureSize;
            }

            if ( /* in some condition */ )
            {
                defaultSetting.textureCompression = TextureImporterCompression.Uncompressed;
            }
            else if (/* in some condition */)
            {
                defaultSetting.format = TextureImporterFormat.Automatic;
            }

            texImporter.SetPlatformTextureSettings(defaultSetting);
            texImporter.ClearPlatformTextureSettings("Android");
            texImporter.ClearPlatformTextureSettings("Standalone");

        }
    }

}

It’s a Preprocessor, so the importer doesn’t need to save and reimport.

Q: how to find the application’s path?

A:

Path.GetDirectoryName( Application.dataPath )

This will return a root of the full path that is relative to the Unity.


Q: How to find the subdirectories in the EditorWindow?

A:

Directory.GetDirectories(dir);
// return the sub directories in dir

// recursively use the method will return all the possible subdirectories in dir
List<string> subdirs = new List<string>();

FindSubdir(dir)

static void FindSubdirectoryRecursion(string directory)
{
    var subdirectories = Directory.GetDirectories(directory);
    foreach (var dir in subdirectories )
    {
        subdirs .Add(dir);
        FindSubdirectoryRecursion(dir);
    }
}

Q: How to access the Importer Settings in EditorWindow?

A:

TextureImporter textureImporter = AssetImporter.GetAtPath(relativePath) as TextureImporter;

Q: Can the EditorWindow output a log?

A:

StreamWriter writer = new StreamWriter(outputPath, true);
writer.WriteLine(outputline);
writer.Close();