Mesh,CombineInstance 实现换装

 CombineInstance 概述:     

         CombineInstance 是 Unity 引擎中用于合并网格的结构体之一。它通过将多个 Mesh 实例组合为一个更大的网格,以减少渲染调用的数量,从而提高性能。

        CombineInstance 结构体包含一系列属性,包括 mesh、transform、subMeshIndex 等,用于指定要合并的网格、变换信息以及子网格索引等。通过使用 CombineInstance,可以将多个网格合并为一个,以便在游戏中高效地渲染。

CombineInstance 实现换装原理:

        我们通过合并多个 Mesh 的数据来实现,其中每个 CombineInstance 实例表示一个待合并的 Mesh。在换装的场景中,通常会有一个基础的角色模型,以及多个不同部位的衣服或装备模型。每个部位的模型可以有不同的 Mesh,例如帽子、上衣、裤子等。

实现解析:

  1. 创建一个新的空的 Mesh,作为最终合并的目标。
  2. 遍历各个部位的模型(例如衣服、装备等),对每个模型创建一个 CombineInstance 实例。
  3. 将待合并的模型的 Mesh 赋值给相应 CombineInstance 的 mesh 属性。
  4. 根据需要,对 CombineInstance 的属性进行设置,例如局部到世界坐标系的变换矩阵 transform、材质 material 等。
  5. 将每个 CombineInstance 实例添加到一个 List 中。
  6. 最后,将 List 中的 CombineInstance 实例数组传入 Mesh.CombineMeshes() 方法进行网格的合并。这会将各个部位的模型的 Mesh 数据合并到目标 Mesh 中。
  7. 合并后的 Mesh 就是换装后的角色模型,它包含了各个部位的模型的几何数据、变换信息等。

代码:

  public GameObject[] arr; //存放需要换装的目标
    void Start()
    {
        Mesh mesh = new Mesh();
        List<CombineInstance> combines=new List<CombineInstance>();
        List<Material> materials=new List<Material>();
        for(int i = 0; i < arr.Length; i++)
        {
           //获取物体的材质 存入集合
            materials.Add(arr[i].GetComponent<MeshRenderer>().material);
            //new CombineInstance
            CombineInstance instance = new CombineInstance();
            //获取物体上的mesh CombineInstance 赋值
            instance.mesh = arr[i].GetComponent<MeshFilter>().mesh;
            //传入一个局部到世界坐标系的变换矩阵,
            //以确保生成的合并网格与原始网格在世界空间中的位置、旋转和缩放保持一致。
            instance.transform = arr[i].transform.localToWorldMatrix;
            //添加到集合中
            combines.Add(instance); 
        }
        //Mesh 的 CombineMeshes 方法会将传入的 CombineInstance 数组中的多个网格合并为一个单独的网格
        mesh.CombineMeshes(combines.ToArray());

        //赋值
        GetComponent<MeshFilter>().mesh=mesh;
        GetComponent<MeshRenderer>().materials=materials.ToArray();
       

        
    }

效果展示: 

》》》

简易的换装就实现啦!!!

简易的换装就实现啦!!!

简易的换装就实现啦!!!

给骨骼换装:

//要换装的物体集合
    public GameObject[] GameList;
    
    void Start()
    {
        //new mesh
        Mesh mesh = new Mesh(); 
        //存储要换装的信息集合
        List<CombineInstance> ComList=new List<CombineInstance>();
        //换装的材质球集合
        List<Material> materialList=new List<Material>();
        //获取我的子物体Transform控件
        Transform[] mybones = GetComponentsInChildren<Transform>();
        //字典 子物体姓名左键 子物体的Transform做值
        Dictionary<string,Transform> dic=new Dictionary<string,Transform>();
        //存放骨骼的集合 
        List<Transform> ghList=new List<Transform>();
        //遍历我的子物体添加到字典
        foreach (var item in mybones)
        {
            dic.Add(item.name, item);
        }
        //遍历换装的物体
        for (int i = 0; i < GameList.Length; i++)
        {
            //获取子物体的材质球 赋值给材质球集合
            materialList.Add(GameList[i].GetComponentInChildren<SkinnedMeshRenderer>().material);

            
            CombineInstance instance = new CombineInstance();
            //获取网格信息并赋值
            instance.mesh = GameList[i].GetComponentInChildren<SkinnedMeshRenderer>().sharedMesh;
            //将物体的本地信息转为世界信息 并赋值
            instance.transform = GameList[i].transform.localToWorldMatrix;
            //将CombineInstance对象添加到集合中
            ComList.Add(instance);
            //根据骨骼 判断我的衣服要穿在哪里
            foreach (var item in GameList[i].GetComponentInChildren<SkinnedMeshRenderer>().bones)
            {
                if(dic.ContainsKey(item.name))
                {
                    //存入骨骼的 集合
                    ghList.Add(dic[item.name]);
                } 
            }
        }
        mesh.CombineMeshes(ComList.ToArray(), false, false);
        //赋值操作
        GetComponent<SkinnedMeshRenderer>().sharedMesh= mesh;
        GetComponent<SkinnedMeshRenderer>().materials=materialList.ToArray();
        GetComponent<SkinnedMeshRenderer>().bones= ghList.ToArray();

    }

猜你喜欢

转载自blog.csdn.net/Steel_nails/article/details/132916122