AssetPostprocessor - Can't change Mesh Data

Hello again,

For the past couple hours I’ve been trying to solve the old: “Blender Axis is different to Unity’s” problem by writing an AssetPostprocessor.

In the Unity Documentation for AssetPostprocessor.OnPostprocessModel it states: “This lets you modify the imported Game Object, Meshes, AnimationClips referenced by it”, however after multiple attempts and a ton of google searches, I have not been able to change any mesh data and have it saved to disk:

import System.IO;

//Fix the ignorance of the standard Blender Importer!!!
class BlenderAssetProcessor extends AssetPostprocessor {
    public function OnPostprocessModel(object:GameObject) {
        var importer : ModelImporter = assetImporter as ModelImporter;
        
        //Only rotate with blender files
        if (Path.GetExtension(importer.assetPath) == ".blend") {
            RotateObject(object);
        }
    }
    
    private function RotateObject(object:GameObject) {
        object.transform.rotation *= Quaternion.Euler(90, 0, 0); //This works and is saved
        
        var meshFilter:MeshFilter = object.GetComponent(MeshFilter);
        if (meshFilter) {
             //Use proven methods to manipulate the mesh data
             ChangeMesh(meshFilter.sharedMesh); //This changes the mesh, but nothing is saved???
        }

        //--some code that calls this recursively for children I left out
    }
 }

I get no errors and everything works absolutely fine, except for the fact that no mesh data is saved.

Has anyone been able to achieve something similar?
Is this even possible, because it definitely should be?!?

Thanks for your help,
Benproductions1

Hello again again,

It turns out that mesh data is not passed by reference but via copy.
For instance:

Vector3[] verts = mesh.vertices;
verts[0] = Vector3.zero;

will not set the first vertex to Vector3.zero
What you need to do is set the vertex array of the mesh

Vector3[] verts = mesh.vertices;
verts[0] = Vector3.zero;
mesh.vertices = verts;

I find this to be counter-intuitive, but what can you do?

Hope this helps anyone else,
Benproductions1

Hope this helps. Tested in v 2020.2.

Make a script file anywhere sub an “Editor” directory in your Project folder. Copy the below. Save it. Reimport your blender folder full of .blend files.

Note, this is for just the meshes. I have not had a stab at skinning data or animation. Only use this for non animated meshes.

using UnityEngine;
using UnityEditor;
 
public class BlenderModelImporter : AssetPostprocessor 
{
 
    void OnPostprocessModel (GameObject g) 
    {
        // Only operate on blender files
        if (assetPath.IndexOf(".blend") == -1) 
        {
            return;
        }

        MeshFilter[] meshf = g.GetComponentsInChildren<MeshFilter>();

        foreach (MeshFilter meshFilter in meshf)
        {
            FixBlenderRotation(meshFilter);
        }
        
        AssetDatabase.Refresh();
    }

    private void FixBlenderRotation(MeshFilter meshFilter)
    {
        Mesh mesh = meshFilter.sharedMesh;

        Matrix4x4 matRot = Matrix4x4.Rotate( Quaternion.Euler(-90,0,0));
        
        Vector3[] rotatedVers = new Vector3[mesh.vertexCount];
        Vector3[] rotatedNormies = new Vector3[mesh.vertexCount];
        for (int i = 0; i < mesh.vertexCount; i++)
        {
            rotatedVers _= matRot * mesh.vertices*;*_

rotatedNormies = matRot * mesh.normals*;*
}

mesh.vertices = rotatedVers;
mesh.normals = rotatedNormies;
mesh.RecalculateBounds();//This makes sure that bounds culling has updated data so that the camera doesn’t stop drawing based on the pre-rotation bounds

//Also bring back the transform rotation to identity so that there’s no weird counter orientation in the game object itself.
meshFilter.transform.localRotation = Quaternion.identity;

}
}