一.模型的整理,了解换装,找到对应指定的模型网格
换装:换装是指在游戏或虚拟场景中,改变角色或物体的外观,通常是通过替换模型、纹理或材质来实现
需要准备多个不同的模型和对应的纹理。每个模型代表一个不同的外观,而纹理则是模型的贴图,用于给模型上色或添加细节。以下是模型各个骨骼部位的网格示例
二.合并多个SkinnedMeshRenderer的网格和纹理,并为合并后的物体创建一个新的Mesh和材质,然后用一个新的Material来渲染合并后的模型
下面附上完整代码,具有详细注释;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CombineMesh : MonoBehaviour
{
//SkinnedMeshRenderer是网格过滤器
public SkinnedMeshRenderer[] sk;
void Start()
{
// 创建一个新的Mesh用于存储合并后的网格数据
Mesh mesh = new Mesh();
// 存储CombineInstance的列表,每个CombineInstance代表一个合并网格的实例
List<CombineInstance> combines = new List<CombineInstance>();
// 存储合并后的纹理
List<Texture2D> textures = new List<Texture2D>();
// 遍历所有的SkinnedMeshRenderer
for (int i = 0; i < sk.Length; i++)
{
CombineInstance instance = new CombineInstance();
// 设置CombineInstance的网格为当前SkinnedMeshRenderer的共享网格
instance.mesh = sk[i].sharedMesh;
// 设置变换矩阵,将网格变换到世界坐标系
instance.transform = sk[i].transform.localToWorldMatrix;
// 将CombineInstance添加到列表中
combines.Add(instance);
// 获取背景纹理并添加到纹理列表中
textures.Add(sk[i].sharedMaterial.GetTexture("_BackTex") as Texture2D);
}
// 使用CombineMeshes方法将所有CombineInstance合并到新的Mesh中
mesh.CombineMeshes(combines.ToArray());
// 创建一个新的纹理用于合并后的网格
Texture2D texture = new Texture2D(0, 0);
// 将纹理列表中的纹理合并到新纹理,并返回合并后的纹理矩形数据
Rect[] rects = texture.PackTextures(textures.ToArray(), 0);
// 重新计算合并后网格的UV坐标
List<Vector2> uv = new List<Vector2>();
for (int i = 0; i < sk.Length; i++)
{
Vector2[] olduv = sk[i].sharedMesh.uv;
for (int j = 0; j < olduv.Length; j++)
{
float uvx = rects[i].x + rects[i].width * olduv[j].x;
float uvy = rects[i].y + rects[i].height * olduv[j].y;
uv.Add(new Vector2(uvx, uvy));
}
}
// 将重新计算的UV坐标应用到新的Mesh上
mesh.uv = uv.ToArray();
// 将新的Mesh赋给物体的MeshFilter组件
GetComponent<MeshFilter>().mesh = mesh;
Texture2D face = sk[0].sharedMaterial.GetTexture("_MainTex") as Texture2D;
// 创建新的材质
Material material = new Material(Shader.Find("Custom/Face"));
// 设置背景纹理
material.SetTexture("_BackTex", texture);
// 设置主纹理
material.SetTexture("_MainTex", sk[0].sharedMaterial.GetTexture("_MainTex"));
// 设置PosX参数,用于纹理坐标映射
material.SetFloat("_PosX", texture.width / face.width);
// 设置PosY参数,用于纹理坐标映射
material.SetFloat("_PosY", texture.height / face.height);
// 将新的材质赋给物体的MeshRenderer组件
GetComponent<MeshRenderer>().material = material;
}
}
设置模型对应部位的网格