Combine mesh with FBX Exporter in unity and export Fbx

The goal is to merge multiple meshes into one or several, reduce drawcall, but don't want to mark it as static, and don't want to make an attempt to merge with 3dmax.
First, install FBX Exporter in Window -> Package Manager. My unity version is 2020, and 2019 should also work.
insert image description here
After successful installation, I found that right-clicking the GameObject can export fbx.
insert image description here

The next step is to merge multiple meshes

Suppose I have such 100 cubes, and I want to merge them into 1 mesh.
insert image description here
First, try exporting directly with Fbx Export.
insert image description here
After exporting, there are still many cubes, which are different from what I want.
insert image description here

My current idea is to read the vertex nv normal information of each mesh, and then when the triangles are in the new mesh, add the number of previous points each time, and it feels that there is no problem connecting the faces.
Then different materials need to be divided into different meshes.

First, get the mesh of all selected objects, and then I temporarily record it in a Dictionary<string, List> meshByMaterial according to the name of the material (the string should be changed to a direct material in the future)

The merged mesh is placed under the newly created object

       GameObject newObjsRoot = new GameObject(name + "__combine");
        newObjsRoot.transform.position = Vector3.zero;
        foreach (KeyValuePair<string, List<MeshFilter>> keyPair in meshByMaterial)
        {
    
    
            //材质一样的mesh 放到一个父物体下
            currentMaterialParent = new GameObject(keyPair.Key).transform;
            currentMaterialParent.transform.SetParent(newObjsRoot.transform);

            CombineMeshes(keyPair.Value);
        }

Every time a new mesh is created, the previous data is cleared

    private static void ClearMeshAttribute()
    {
    
    
        vertices = new List<Vector3>();
        uvs = new List<Vector2>();
        normals = new List<Vector3>();
        indices = new List<int>();
        // addMaxIndics = 0;

        tangents = new List<Vector4>();
        addMaxIndics = 0;

    }

Get the position of the vertices of each mesh in world coordinates


        for (int i = 0; i < newVertices.Length; i++)
        {
    
    
            vertices.Add(meshObj.transform.TransformPoint(newVertices[i]));
        }

Store a V3 of the scaling direction of the GameObject. If the Obj has a negative scaling, the normal and traingle order need to be changed.

 Vector3 fixV3 = new Vector3(
                     meshObj.transform.localScale.x < 0 ? -1 : 1,
                     meshObj.transform.localScale.y < 0 ? -1 : 1,
                     meshObj.transform.localScale.z < 0 ? -1 : 1
                 );

store normals

        for (int i = 0; i < newNormals.Length; i++)
        {
    
    
            newNormals[i] = new Vector3(
                newNormals[i].x * fixV3.x,
                newNormals[i].y * fixV3.y,
                newNormals[i].z * fixV3.z
            );
        }

// local scale is negative to reverse the face

   
        if (fixV3.x * fixV3.y * fixV3.z < 0)
        {
    
    
            for (int i = 0; i < newIndices.Length; i += 3)
            {
    
    
                int change = newIndices[i + 1];

                newIndices[i + 1] = newIndices[i + 2];
                newIndices[i + 2] = change;

            }

        }

Then each number in the Indices of each mesh is added to the number of vertices stored in the mesh before. After finishing the work, save the number of vertices of the current mesh

 for (int i = 0; i < newIndices.Length; i++)
        {
    
    
            int index = newIndices[i] + addMaxIndics;
            indices.Add(index);

        }
          addMaxIndics = vertices.Count;

Then I found that when there are too many vertices, the surface will be very strangely damaged. After checking, someone said that unitymesh has a maximum vertex limit of 65535, so if it exceeds this number, create a new mesh storage.

    if (newVertices.Length + vertices.Count >= maxVerticesCount)
        {
    
    
            CreateNewMesh(material);
            ClearMeshAttribute();
        }

Finally, CreateNewMesh assigns a value to the mesh and generates

Click Window/combineMeshEditor and FBX Exporter
insert image description here
appears in the scene insert image description here
. After exporting, it can be seen that it is a mesh
insert image description here

TODO Use Unity's CombineMeshes to complete the above functions

Project address https://gitee.com/go_x/unity-project.git

Guess you like

Origin blog.csdn.net/weixin_38926960/article/details/124276313