CombineInstance 概述:
CombineInstance 是 Unity 引擎中用于合并网格的结构体之一。它通过将多个 Mesh 实例组合为一个更大的网格,以减少渲染调用的数量,从而提高性能。
CombineInstance 结构体包含一系列属性,包括 mesh、transform、subMeshIndex 等,用于指定要合并的网格、变换信息以及子网格索引等。通过使用 CombineInstance,可以将多个网格合并为一个,以便在游戏中高效地渲染。
CombineInstance 实现换装原理:
我们通过合并多个 Mesh 的数据来实现,其中每个 CombineInstance 实例表示一个待合并的 Mesh。在换装的场景中,通常会有一个基础的角色模型,以及多个不同部位的衣服或装备模型。每个部位的模型可以有不同的 Mesh,例如帽子、上衣、裤子等。
实现解析:
- 创建一个新的空的 Mesh,作为最终合并的目标。
- 遍历各个部位的模型(例如衣服、装备等),对每个模型创建一个 CombineInstance 实例。
- 将待合并的模型的 Mesh 赋值给相应 CombineInstance 的 mesh 属性。
- 根据需要,对 CombineInstance 的属性进行设置,例如局部到世界坐标系的变换矩阵 transform、材质 material 等。
- 将每个 CombineInstance 实例添加到一个 List 中。
- 最后,将 List 中的 CombineInstance 实例数组传入 Mesh.CombineMeshes() 方法进行网格的合并。这会将各个部位的模型的 Mesh 数据合并到目标 Mesh 中。
- 合并后的 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();
}