public List <GameObject> CombineToMeshes(List <MeshRenderer> meshRenderers, List <SkinnedMeshRenderer> skinnedMeshRenderers, Transform parent, int combinedIndex)
        {
            // The list of Meshes created
            List <GameObject> combinedMeshes = new List <GameObject>();
            // The list of _combineInstances
            CombineInstanceID combineInstances = new CombineInstanceID();

            int verticesCount           = 0;
            int combinedGameObjectCount = 0;

            // Process meshes for combine process
            for (int i = 0; i < meshRenderers.Count; i++)
            {
                for (int j = 0; j < meshRenderers[i].GetComponent <MeshFilter>().sharedMesh.subMeshCount; j++)
                {
                    // Get a copy of the submesh at index j
                    Mesh newMesh = SubmeshSplitter.ExtractSubmesh(meshRenderers[i].GetComponent <MeshFilter>().sharedMesh, j);

                    verticesCount += newMesh.vertexCount;
                    if (verticesCount > _maxVerticesCount)
                    {
                        combinedMeshes.Add(CreateCombinedMeshGameObject(combineInstances, parent, combinedGameObjectCount, combinedIndex));
                        combineInstances.Clear();
                        combinedGameObjectCount++;
                        verticesCount = newMesh.vertexCount;
                    }

                    // Create the list of CombineInstance for this mesh
                    Matrix4x4 matrix = parent.transform.worldToLocalMatrix * meshRenderers[i].transform.localToWorldMatrix;
                    combineInstances.AddRange(CreateCombinedInstances(newMesh, new Material[] { meshRenderers[i].sharedMaterials[j] }, meshRenderers[i].gameObject.GetInstanceID(), meshRenderers[i].gameObject.name, matrix, combinedIndex));
                }
            }

            for (int i = 0; i < skinnedMeshRenderers.Count; i++)
            {
                for (int j = 0; j < meshRenderers[i].GetComponent <MeshFilter>().sharedMesh.subMeshCount; j++)
                {
                    // Get a snapshot of the sub skinnedMesh renderer at index j
                    Mesh newMesh = SubmeshSplitter.ExtractSubmesh(skinnedMeshRenderers[i].sharedMesh, j);

                    _vertexOffset += newMesh.vertexCount;

                    verticesCount += newMesh.vertexCount;
                    if (verticesCount > _maxVerticesCount && combineInstances.Count() > 0)
                    {
                        combinedMeshes.Add(CreateCombinedMeshGameObject(combineInstances, parent, combinedGameObjectCount, combinedIndex));
                        combineInstances.Clear();
                        combinedGameObjectCount++;
                        verticesCount = newMesh.vertexCount;
                    }

                    // Create the list of CombineInstance for this skinnedMesh
                    Matrix4x4 matrix = parent.transform.worldToLocalMatrix * skinnedMeshRenderers[i].transform.localToWorldMatrix;
                    combineInstances.AddRange(CreateCombinedInstances(newMesh, new Material[] { skinnedMeshRenderers[i].sharedMaterials[j] }, skinnedMeshRenderers[i].GetInstanceID(), skinnedMeshRenderers[i].gameObject.name, matrix, combinedIndex));
                }
            }


            if (combineInstances.Count() > 0)
            {
                // Create the combined GameObject which contains the combined meshes
                combinedMeshes.Add(CreateCombinedMeshGameObject(combineInstances, parent, combinedGameObjectCount, combinedIndex));
            }

            return(combinedMeshes);
        }
        public List <GameObject> CombineToSkinnedMeshes(List <MeshRenderer> meshRenderers, List <SkinnedMeshRenderer> skinnedMeshRenderers, Transform parent, int combinedIndex)
        {
            // The list of Meshes created
            List <GameObject> combinedMeshes = new List <GameObject>();
            // The list of _combineInstances
            CombineInstanceID combineInstances = new CombineInstanceID();

            int verticesCount           = 0;
            int combinedGameObjectCount = 0;

            /*
             *          / Skinned mesh parameters
             */
            // List of bone weight
            List <BoneWeight> boneWeights = new List <BoneWeight>();
            // List of bones
            List <Transform> bones = new List <Transform>();
            // List of bindposes
            List <Matrix4x4> bindposes = new List <Matrix4x4>();
            // List of original bones mapped to their instanceId
            Dictionary <int, Transform> originalBones = new Dictionary <int, Transform>();
            // Link original bone instanceId to the new created bones
            Dictionary <int, Transform> originToNewBoneMap = new Dictionary <int, Transform>();
            // The vertices count
            int boneOffset = 0;

            // Get bones hierarchies from all skinned mesh
            for (int i = 0; i < skinnedMeshRenderers.Count; i++)
            {
                foreach (Transform t in skinnedMeshRenderers[i].bones)
                {
                    if (!originalBones.ContainsKey(t.GetInstanceID()))
                    {
                        originalBones.Add(t.GetInstanceID(), t);
                    }
                }
            }

            // Find the root bones
            Transform[] rootBones = FindRootBone(originalBones);
            for (int i = 0; i < rootBones.Length; i++)
            {
                // Instantiate the GameObject parent for this rootBone
                GameObject rootBoneParent = new GameObject("rootBone" + i);
                rootBoneParent.transform.position       = rootBones[i].position;
                rootBoneParent.transform.parent         = parent;
                rootBoneParent.transform.localPosition -= rootBones[i].localPosition;
                rootBoneParent.transform.localRotation  = Quaternion.identity;

                // Instanciate a copy of the root bone
                GameObject newRootBone = InstantiateCopy(rootBones[i].gameObject);
                newRootBone.transform.position = rootBones[i].position;
                newRootBone.transform.rotation = rootBones[i].rotation;
                newRootBone.transform.parent   = rootBoneParent.transform;
                newRootBone.AddComponent <MeshRenderer>();

                // Get the correspondancy map between original bones and new bones
                GetOrignialToNewBonesCorrespondancy(rootBones[i], newRootBone.transform, originToNewBoneMap);
            }

            // Copy Animator Controllers to new Combined GameObject
            foreach (Animator anim in parent.parent.GetComponentsInChildren <Animator>())
            {
                Transform[] children = anim.GetComponentsInChildren <Transform>();
                // Find the transform into which a copy of the Animator component will be added
                Transform t = FindTransformForAnimator(children, rootBones, anim);
                if (t != null)
                {
                    CopyAnimator(anim, originToNewBoneMap[t.GetInstanceID()].parent.gameObject);
                }
            }

            for (int i = 0; i < skinnedMeshRenderers.Count; i++)
            {
                // Get a snapshot of the skinnedMesh renderer
                Mesh mesh = copyMesh(skinnedMeshRenderers[i].sharedMesh, skinnedMeshRenderers[i].GetInstanceID().ToString());
                _vertexOffset += mesh.vertexCount;

                verticesCount += skinnedMeshRenderers[i].sharedMesh.vertexCount;
                if (verticesCount > _maxVerticesCount && combineInstances.Count() > 0)
                {
                    // Create the new GameObject
                    GameObject combinedGameObject = CreateCombinedSkinnedMeshGameObject(combineInstances, parent, combinedGameObjectCount, combinedIndex);
                    // Assign skinnedMesh parameters values
                    SkinnedMeshRenderer sk = combinedGameObject.GetComponent <SkinnedMeshRenderer>();
                    AssignParametersToSkinnedMesh(sk, bones, boneWeights, bindposes);
                    combinedMeshes.Add(combinedGameObject);
                    boneOffset = 0;

                    combineInstances.Clear();
                    combinedGameObjectCount++;
                    verticesCount = skinnedMeshRenderers[i].sharedMesh.vertexCount;
                }


                // Copy bone weights
                BoneWeight[] meshBoneweight = skinnedMeshRenderers[i].sharedMesh.boneWeights;
                foreach (BoneWeight bw in meshBoneweight)
                {
                    BoneWeight bWeight = bw;
                    bWeight.boneIndex0 += boneOffset;
                    bWeight.boneIndex1 += boneOffset;
                    bWeight.boneIndex2 += boneOffset;
                    bWeight.boneIndex3 += boneOffset;

                    boneWeights.Add(bWeight);
                }
                boneOffset += skinnedMeshRenderers[i].bones.Length;

                // Copy bones and bindposes
                Transform[] meshBones = skinnedMeshRenderers[i].bones;
                foreach (Transform bone in meshBones)
                {
                    bones.Add(originToNewBoneMap[bone.GetInstanceID()]);
                    bindposes.Add(bone.worldToLocalMatrix * parent.transform.localToWorldMatrix);
                }

                // Create the list of CombineInstance for this skinnedMesh
                Matrix4x4 matrix = parent.transform.worldToLocalMatrix * skinnedMeshRenderers[i].transform.localToWorldMatrix;
                combineInstances.AddRange(CreateCombinedInstances(mesh, skinnedMeshRenderers[i].sharedMaterials, skinnedMeshRenderers[i].GetInstanceID(), skinnedMeshRenderers[i].gameObject.name, matrix, combinedIndex));
            }

            if (combineInstances.Count() > 0)
            {
                // Create the combined GameObject which contains the combined meshes
                // Create the new GameObject
                GameObject combinedGameObject = CreateCombinedSkinnedMeshGameObject(combineInstances, parent, combinedGameObjectCount, combinedIndex);
                // Assign skinnedMesh parameters values
                SkinnedMeshRenderer sk = combinedGameObject.GetComponent <SkinnedMeshRenderer>();
                AssignParametersToSkinnedMesh(sk, bones, boneWeights, bindposes);
                combinedMeshes.Add(combinedGameObject);
            }

            return(combinedMeshes);
        }