合并SkinnedMeshRender实现换装

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class CombineSkinnedMeshMananger
{

    private const int MAXTEXTURESIZE = 512;
    public void CombineSkinnedMeshRender(GameObject instance, SkinnedMeshRenderer[] skinnedMeshRenderers,bool isCombine =false)
    {
        if (instance == null)
        {
            return;
        }
        List<Transform> transforms = new List<Transform>();
        transforms.AddRange(instance.GetComponentsInChildren<Transform>(true));
        
        List<CombineInstance> combineInstances = new List<CombineInstance>(); //网格
        List<Transform> bones = new List<Transform>(); //骨骼
        List<Material> materials= new List<Material>(); //材质

        if (skinnedMeshRenderers == null || skinnedMeshRenderers.Length == 0)
        {
            return;
        }

        for (int i = 0; i < skinnedMeshRenderers.Length; i++)
        {
            SkinnedMeshRenderer smr = skinnedMeshRenderers[i];
            //收集材质
            materials.AddRange(smr.materials);
            //收集网格
            for (int j = 0; j < smr.sharedMesh.subMeshCount; j++)
            {
                CombineInstance combineInstance = new CombineInstance();
                combineInstance.mesh = smr.sharedMesh;
                combineInstance.subMeshIndex = j;
                combineInstances.Add(combineInstance);
            }
            
            //收集骨骼
            for (int j = 0; j < smr.bones.Length; j++)
            {
                for (int k = 0; k < transforms.Count; k++)
                {
                    if (smr.bones[j].name.Equals(transforms[k].name))
                    {
                        bones.Add(transforms[k]);
                        break;
                    }
                }
            }
        }

        List<Vector2[]> oldUV = null;
        Material newMaterila = null;
        Texture2D newDiffuseTex = null;
        //合并材质
        if (isCombine)
        {
            //这里材质类型和没有合并之前的材质类型要保持一直
            newMaterila = new Material(Shader.Find("Mobile/Diffuse"));
            oldUV = new List<Vector2[]>();
            
            //合并贴图
            List<Texture2D> textures = new List<Texture2D>();
            for (int i = 0; i < materials.Count; i++)
            {
                textures.Add(materials[i].GetTexture("_MainTex") as Texture2D);
            }
            newDiffuseTex = new Texture2D(MAXTEXTURESIZE,MAXTEXTURESIZE,TextureFormat.RGBA32,true);
            Rect[] uvs = newDiffuseTex.PackTextures(textures.ToArray(), 0);
            newMaterila.mainTexture = newDiffuseTex;
            
            //重置UV ???
            Vector2[] uva, uvb;
            for (int j = 0; j < combineInstances.Count; j++)
            {
                uva = combineInstances[j].mesh.uv;
                uvb = new Vector2[uva.Length];
                for (int k = 0; k < uva.Length; k++)
                {
                    uvb[k] = new Vector2((uva[k].x * uvs[j].width) + uvs[j].x, (uva[k].y * uvs[j].height) + uvs[j].y);
                }
                oldUV.Add(combineInstances[j].mesh.uv);
                combineInstances[j].mesh.uv = uvb;
            }
        }

        //重新绑定SkinnedMeshRenderer
        SkinnedMeshRenderer oldSkinnedMeshRenderer = instance.GetComponent<SkinnedMeshRenderer>();
        if (oldSkinnedMeshRenderer != null)
        {
            GameObject.DestroyImmediate(oldSkinnedMeshRenderer);
        }
        SkinnedMeshRenderer skinnedMeshRenderer = instance.AddComponent<SkinnedMeshRenderer>();
        skinnedMeshRenderer.sharedMesh = new Mesh();
        skinnedMeshRenderer.sharedMesh.CombineMeshes(combineInstances.ToArray(), isCombine,false);
        skinnedMeshRenderer.bones = bones.ToArray();
        if (isCombine)
        {
            skinnedMeshRenderer.material = newMaterila;
            //??? 这里为啥又换回来了
            for (int i = 0 ; i < combineInstances.Count ; i ++)
            {
                combineInstances[i].mesh.uv = oldUV[i];
            }
        }
        else
        {
            skinnedMeshRenderer.materials = materials.ToArray();
        }
    }
    
}

 

posted @ 2021-12-06 16:38  围墙外的世界  阅读(536)  评论(0编辑  收藏  举报