Combine Mesh and Texture (sources to share)

hi,guys,glad to share a script!
put it in character,it can combine mesh and texture.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;

public class CombineMesher : MonoBehaviour
{
   
   
    void Start()
    {
    Combine(transform);
    }
   
   
   
    public Transform Combine(Transform root)
    {
    float startTime = Time.realtimeSinceStartup;
   
    // The SkinnedMeshRenderers that will make up a character will be
    // combined into one SkinnedMeshRenderers using one material.
    // This will speed up rendering the resulting character.
    // note:each SkinnedMeshRenderer must share a same material
    List<CombineInstance> combineInstances = new List<CombineInstance>();
    List<Material> materials = new List<Material>();
    Material material = null;
    List<Transform> bones = new List<Transform>();
    Transform[] transforms = root.GetComponentsInChildren<Transform>();
    List<Texture2D> textures = new List<Texture2D>();
    int width = 0;
    int height = 0;
   
    int uvCount = 0;
   
    List<Vector2[]> uvList = new List<Vector2[]>();
   
    foreach (SkinnedMeshRenderer smr in root.GetComponentsInChildren<SkinnedMeshRenderer>())
    {
        if (material == null)
        material = Instantiate(smr.sharedMaterial) as Material;
        for (int sub = 0; sub < smr.sharedMesh.subMeshCount; sub++)
        {
            CombineInstance ci = new CombineInstance();
            ci.mesh = smr.sharedMesh;
            ci.subMeshIndex = sub;
            combineInstances.Add(ci);
        }
       
        uvList.Add(smr.sharedMesh.uv);
        uvCount += smr.sharedMesh.uv.Length;
       
        if (smr.material.mainTexture != null)
        {
            textures.Add(smr.renderer.material.mainTexture as Texture2D);
            width += smr.renderer.material.mainTexture.width;
            height += smr.renderer.material.mainTexture.height;
        }
       
        // we need to recollect references to the bones we are using
        foreach (Transform bone in smr.bones)
        {
            foreach (Transform transform in transforms)
            {
                if (transform.name != bone.name) continue;
                bones.Add(transform);
                break;
            }
        }
        Object.Destroy(smr.gameObject);
    }
   
    // Obtain and configure the SkinnedMeshRenderer attached to
    // the character base.
    SkinnedMeshRenderer r = root.gameObject.GetComponent<SkinnedMeshRenderer>();
    if (!r)
    r = root.gameObject.AddComponent<SkinnedMeshRenderer>();
   
    r.sharedMesh = new Mesh();
   
    //only set mergeSubMeshes true will combine meshs into single submesh
    r.sharedMesh.CombineMeshes(combineInstances.ToArray(), true, false);
    r.bones = bones.ToArray();
    r.material = material;
   
    Texture2D skinnedMeshAtlas = new Texture2D(1024, 512);
    Rect[] packingResult = skinnedMeshAtlas.PackTextures(textures.ToArray(), 0);
    Vector2[] atlasUVs = new Vector2[uvCount];
   
    //as combine textures into single texture,so need recalculate uvs
   
    int j = 0;
    for (int i = 0; i < uvList.Count; i++)
    {
        foreach (Vector2 uv in uvList[i])
        {
            atlasUVs[j].x = Mathf.Lerp(packingResult[i].xMin, packingResult[i].xMax, uv.x);
            atlasUVs[j].y = Mathf.Lerp(packingResult[i].yMin, packingResult[i].yMax, uv.y);
            j++;
        }
    }
   
        r.material.mainTexture = skinnedMeshAtlas;
        r.sharedMesh.uv = atlasUVs;
       
        Debug.Log("combine meshes takes : " + (Time.realtimeSinceStartup - startTime) * 1000 + " ms");
        return root;
    }
}

Not perfect is it can’t combine normal texture.
enjoy it!
thanks

by the way,i forget to notice you have to set texture read/write flag.Otherwise will give a error!
im sorry to my English.
but have a nice day!

Thanks for sharing it. Helped me a lot. Extending it to use other maps for pbr workflow shoudln’t be that hard I think.