1 做好裸模,绑好骨骼,k好动作。
2 做出模型需要更换的装备,刷好权重。每个部位需要拆分成单独的模型。比如衣服,鞋子,裤子等。
3 导出裸模与装备模型到unity,每种模型都需要包含骨骼,因为换装依赖的组件是SkinnedMeshRenderer,只有包含骨骼的模型,导入到unity中才会生成该组件。不包含骨骼的模型,导入到unity中只会生成Mesh Renderer。
一定不要忘记勾选Read/Write Enabled,不勾选就不能读取模型中的顶点数据,从而无法正常实现换装功能了。
4 将导入的模型做成预制体,放到Resources目录下备用。
5 将裸模拖动到场景中,增加换装脚本。
换装具体思路为,从resources中加载各装备的预制文件,并生成相应的gameobject,再从生成的gameobject的SkinnedMeshRenderer组件中读取当前装备模型的顶点,材质,骨骼等数据。待所有需要更换的数据读取完成后,更新场景中裸模的skinnedMeshRenderer组件信息,从而实现换装。
因为没有正式代码,都是测试用的,就不贴代码了,用伪代码代替吧。
GameObject baseModel;
Transform[] allBones;
void Start(){
baseModel=this.gameObject;
//获取裸模所有的子物体数据(主要是裸模包含的骨骼数据)
allBones=baseModel.GetComponentsInChildren<Transform>();
//新建一个集合,用来存储各部件装备的实例化对象
List<GameObject> equips=new List<GameObject>();
equips.add(GameObject.Instantiate(Resources.Load("衣服模型预制") as GameObject));
equips.add(GameObject.Instantiate(Resources.Load("裤子模型预制") as GameObject));
equips.add(GameObject.Instantiate(Resources.Load("鞋子模型预制") as GameObject));
List<CombineInstance> combines=new List<CombineInstance>();
List<Transform> combineBones=new List<Transform>();
List<Material> materials=new List<>(Material);
//遍历实例化对象的SkinnedMeshRenderer组件,取出顶点骨骼材质数据
foreach(GameObject equip in equips){
//获取实例化装备对象的skinnedMeshRenderer组件进行后续操作
//可能存在一个模型包含多个物体,也就会出现多个skinnedmeshrenderer对象,所以要获取全部的smr并进行处理
SkinnedMeshRenderer[] smrs=equip.getComponentsInChildren<SkinnedMeshRenderer>();
foreach(SkinnedMeshRenderer smr in smrs){
materials.AddRange(smr.materials);
//获取smr对象中包含的网格数据 存储到combineInstance对象中,以便后续进行合并操作
for(int x=0;x<smr.sharedMesh.subMeshCount;x++){
CombineInstance cInstance=new CombineInstance();
cInstance.subMeshIndex=x;
cInstance.mesh=smr.sharedMesh;
combines.Add(cInstance);
}
//遍历骨骼信息
for(int x=0;x<smr.bones.Length;x++){
foreach(Transform bone in allBones){
if(smr.bones[x].name==bone.name){
combineBones.Add(bone);
}
}
}
}
//数据处理完成后,销毁生成的装备预制体
Destory(equip);
}
//合并提取的数据,生成新的SkinnedMeshRender,设置到裸模中
SkinnedMeshRenderer newSmr = baseModel.AddComponent<SkinnedMeshRenderer>();
newSmr.sharedMesh = new Mesh();
newSmr.bones = combineBones.ToArray();
newSmr.sharedMesh.CombineMeshes(combines.ToArray(), false, false);
newSmr.materials = mats.ToArray();
}