Dev-Bites: Unity AssetPostprocessor

When working with .blend files in Unity, developers often encounter several day-to-day impediments. Importing these files is quite easy, as Unity can transform them into FBX files and auto-generate prefabs, allowing us to use them directly from the assets folder. This feature works well for simple models, but as complexity increases, issues begin to arise and stuff falls apart:

  • Lights and cameras from the .blend file are also imported.
  • If multiple models are designed in the same file, we may only want a single one per auto-generated prefab.
  • We may need to add custom components, colliders, and more to the prefab.
  • Cleaning up the model after import can be tedious, especially when slight changes to the .blend file require repeating the process.
  • So many more issues …

Good news: Unity provides pre- and post-processors to hook into the asset import process at different stages, allowing us to define how to import assets. In general, processors are either pre-processors (applied before a specific action takes place) or post-processors (applied after the action). and there are many of them available.

Let’s assume we want to import a model and, after the import, scale it down, attach some components, maybe add a child GameObject, and replace its material. All of this can be done using post-processors.

public class PostprocessorsFishImport : AssetPostprocessor
{
    void OnPostprocessModel(GameObject gameObject)
    {
        //Filter for specific Files, otherwise all .blend Files will be processed
        if (gameObject.name.StartsWith("SmallAnimal_Fish_"))
        {
            //Add Child GameObject
            GameObject child = new GameObject("PlacementAnchor");
            child.transform.parent = gameObject.transform;

            //Add Components
            gameObject.AddComponent<Animator>();
            gameObject.AddComponent<FishEntity>();
            gameObject.AddComponent<PlayerLiquidDetect>();

            //Try to add Material
            Material material = (Material)Resources.Load("Materials/MaterialSmallAnimalFish_" + gameObject.name.Replace("SmallAnimal_Fish_", ""), typeof(Material));

            if (material != null)
            {
                foreach (MeshRenderer meshRenderer in gameObject.GetComponentsInChildren<MeshRenderer>())
                {
                    meshRenderer.sharedMaterial = material;
                }
            }

            //Try to add Animator
            AnimatorController animatorController = (AnimatorController)Resources.Load("Animations/FishAnimation/FishAnimation_" + gameObject.name.Replace("SmallAnimal_Fish_", ""), typeof(AnimatorController));

            if (animatorController != null)
            {
                gameObject.GetComponent<Animator>().runtimeAnimatorController = animatorController;
            }

            //Scale down a bit
            gameObject.transform.localScale = new Vector3(0.03125f, 0.03125f, 0.03125f);
        }
    }
}

In this simple post-processor, we receive a GameObject generated by Unity using the .blend files. We can manipulate or extend this GameObject freely. Once the method exits, the GameObject is turned into a Prefab accessible in the Unity editor.

You have to extend the classes containing your pre- and post-processors from AssetPostprocessor (yes, this includes pre-processors) and Unity will detect and use them automatically. This comes with a catch: the AssetPostprocessor is an editor tool, so it can’t be compiled during build. To circumvent that issue, you can store your code in an Editor-folder, which will be ignored when you do a production build.

From now on, if a .blend file changes, Unity will detect these changes and run your custom post-processor. Depending on your individual needs, this may save you a significant amount of work in the long run.

Leave a Reply

Your email address will not be published. Required fields are marked *

Navigation

Home

Media

Download current Version

More resources to discover will follow in the foreseeable future.