Blend Shapes Changing Vertex Normals

With the Unity 2019.3.0f6 you can forget this script. I have tons of characters with blendshapes and blendshape normal issue is fixed.
My settings:
mesh compression off
optimize mesh, yes
normals calculate
normals mode area & angle weighted
smoothing angle 180 (you might want to give few tests with this)

2 Likes

Dude ur a life saver! Problem fixed mesh looking great!

Also for other people struggling with this I got the normals to look better by setting Smoothness Source to From Angle and Smoothing Angle to 180. But this script cleaned everything up perfectly for me.

1 Like

I tried that version yesterday, problem still exists for my situation. The script in this thread fixed my problems.

FBX does not apply lock normal mode if mesh has blendshapes.

None of the options in 【Blend Shape Normals】makes my model in blend-shape look better.
So I go back to Blender, interchange the blend-shape and the default-state (let the blend-shape be the default-state, let the default-state be the blend-shape), and reverse the animation.
This new model gives a good look in Unity. Hope it can be helpful.

5942966--636278--2020-06-05-17-33-36.gif

Hi. @thomh_unity

Got the same issue with FBX from Modo with Blendshape and VertexNormal map saved at exported.
and even with the 2 CS Script i can’t solved it in 2017.4 Unity release.

i hope we can switch to 2019.4.0 (where it works well). Developer will tell me, if we can migrate the project.

hope we can solve that.

I’m currently working with Unity 2019.4.21f1 and there are still issues with fbx blendshape import.

Currently, whatever import settings I choose, if I change the “scale factor” to anything but 1 (currently using 0.01)
If I set normals to ‘import’, the nornamls are messd up badly.
If I set normals to calculate, same issue.
If i set normals to none, the normals actually “appear” to be correct, but the delta vertices positions are messed up

If I set the scale factor to 1 everything works as expected.

The only solution helping me was the script provided by thomh_unity.

I just hit this problem (smoothing groups error), upgrading from 2019 to 2022 LTS. In my case the issue was there is a checkbox for import legacy normals. Once this is unchecked there are other options which worked fine. I am importing directly from a Blender file.

Bumping the thread to confirm this worked also for me in Unity 2023.1.9. Was becoming crazy checking where I messed my vertex groups or normals in Blender. Thank you!

ps. Oh boy, the satisfaction of being able to make my character blink in a natural random way without strange normals anymore…

Many years later, and this issue is still not fixed. I had to use the script from this thread to fix normals for blendshapes in Unity 2021…

The script above relies on old bone weight structure and copies only 4 bone weights, breaking weight painting for more complex models.

Here is an updated version to correctly copy all bones:

using UnityEngine;
using UnityEditor;

public class FixNormals
{
    /*
     * Set the normals for each blend shape frame to the
     * same normals as the base mesh and export a new mesh
     * asset with a sensible name. Select a mesh, right
     * click and choose 'Generate Mesh With Fixed Normals'.
     */
    [MenuItem("Assets/Generate Mesh With Fixed Normals")]
    private static void FixBlendShapeNormals()
    {

        if(Selection.activeObject.GetType() != typeof(Mesh))
        {
            Debug.LogError("This isn't a mesh.");
            return;
        }

        Debug.Log("let's fix these blendshape normals!");

        Mesh selected = Selection.activeObject as Mesh;
    
        Vector3[] deltaVertices = new Vector3[selected.vertexCount];
        Vector3[] deltaNormals = new Vector3[selected.vertexCount];
        Vector3[] deltaTangents = new Vector3[selected.vertexCount];

        int bsc = selected.blendShapeCount;

        Mesh newMesh = new Mesh();
        newMesh.vertices = selected.vertices;
        newMesh.uv = selected.uv;
        newMesh.normals = selected.normals;
        newMesh.colors = selected.colors;
        newMesh.tangents = selected.tangents;
        newMesh.subMeshCount = selected.subMeshCount;
        //newMesh.triangles = selected.triangles;

        int subMeshes = selected.subMeshCount;
        for (int i = 0; i < subMeshes; i++) {
            int[] tris = selected.GetTriangles(i);
            newMesh.SetIndices(tris, MeshTopology.Triangles, i);
        }

        newMesh.name = selected.name + "_fixed";
        var bonesPerVertex = selected.GetBonesPerVertex();
        var boneWeights = selected.GetAllBoneWeights();
        newMesh.SetBoneWeights(bonesPerVertex, boneWeights);
        newMesh.bindposes = selected.bindposes;

        for (int i = 0; i< bsc; i++)
        {
            string name = selected.GetBlendShapeName(i);
            int weightCount = selected.GetBlendShapeFrameCount(i);
            for (int j = 0; j < weightCount; j++)
            {
                float weight = selected.GetBlendShapeFrameWeight(i, j);
                selected.GetBlendShapeFrameVertices(i, j, deltaVertices, deltaNormals, deltaTangents);
                newMesh.AddBlendShapeFrame(name, weight, deltaVertices, selected.normals, deltaTangents);
            }
        }

        string savePath = AssetDatabase.GetAssetPath(selected);
        savePath = savePath.Substring(0, savePath.LastIndexOf('/') + 1);
    
        string newAssetName = savePath + selected.name + "_fixed.asset";

        AssetDatabase.CreateAsset(newMesh, newAssetName);

        AssetDatabase.SaveAssets();

        Debug.Log("Done!");
    }
}
1 Like