unity换装系统+网格合并
这里的做法是模型把所有衣服全部穿上作为一个资源
然后还有一个只有骨骼信息的骨架资源
将这2个制作好了Prefab
模型部件数据
资源数据
【代码】
using System.Collections; using System.Collections.Generic; using UnityEngine; public class AvatarSystem : MonoBehaviour { //模型全文件 GameObject modelObject; Transform modelSource; //骨骼文件 GameObject targetSource; Transform targetTrans; //Data字典 存储source的各种信息; private Dictionary<string, Dictionary<string, Transform>> data = new Dictionary<string, Dictionary<string, Transform>>(); //targetSmr字典 存储目标的骨骼信息 private Dictionary<string, SkinnedMeshRenderer> targetSmr = new Dictionary<string, SkinnedMeshRenderer>(); //骨骼数组 private Transform[] hips; //套装数据 string[,] avatarStr = new string[,] { { "Glove", "suit01" }, { "Head", "suit01" }, { "Hair", "suit01" }, { "Body", "suit02" }, { "Leg", "suit03" }, { "Shoe", "suit03" } }; // Use this for initialization void Start () { InstantiateAvatar("Prefab/Model_girl");//读取模型文件 InstantiateSkeleton("Prefab/Target_girl");//读取骨架文件 LoadAvatarData(modelSource);//读取模型所有衣服数据,并且存储 hips = targetTrans.GetComponentsInChildren<Transform>();//拿取人物骨骼信息 Inivatar(avatarStr);//换上套装 //targetSource.AddComponent<Animator>(); } // Update is called once per frame void Update () { } //实例化来源 void InstantiateAvatar(string modelName) { //必需得实例化出来,不然无法获得数据 modelObject = (Instantiate(Resources.Load<GameObject>(modelName))); modelSource = modelObject.transform; modelSource.gameObject.SetActive(false);//隐藏 //Destroy(modelObject);//销毁 } //实例化骨架(换装就是在骨架上加衣服) void InstantiateSkeleton(string targetName) { targetSource = Instantiate(Resources.Load<GameObject>(targetName)); targetTrans = targetSource.transform; } //读取来源的各种信息(source模型源文件) void LoadAvatarData(Transform source) { if (source == null) { return; } SkinnedMeshRenderer[] parts = source.GetComponentsInChildren<SkinnedMeshRenderer>(true); foreach (SkinnedMeshRenderer part in parts) { string[] partName = part.name.Split('_'); if (!data.ContainsKey(partName[0])) { data.Add(partName[0], new Dictionary<string, Transform>()); GameObject partObj = new GameObject(); partObj.name = partName[0]; partObj.transform.parent = targetTrans; targetSmr.Add(partName[0], partObj.AddComponent<SkinnedMeshRenderer>()); } data[partName[0]].Add(partName[1], part.transform); } } //更改Mesh public void ChangeMesh(string part, string item) { SkinnedMeshRenderer smr = data[part][item].GetComponent<SkinnedMeshRenderer>(); //网格合并 List<CombineInstance> combineInstances = new List<CombineInstance>(); for (int i = 0; i < smr.sharedMesh.subMeshCount; i++) { CombineInstance ci = new CombineInstance(); ci.mesh = smr.sharedMesh; ci.subMeshIndex = i; combineInstances.Add(ci); } List<Transform> bones = new List<Transform>(); foreach (Transform bone in smr.bones) { foreach (Transform hip in hips) { if (hip.name != bone.name) { continue; } bones.Add(hip); break; } } //网格合并方式 targetSmr[part].sharedMesh = new Mesh(); targetSmr[part].sharedMesh.CombineMeshes(combineInstances.ToArray(), false, false); //非网格合并方式 //targetSmr[part].sharedMesh = smr.sharedMesh; targetSmr[part].bones = bones.ToArray(); targetSmr[part].materials = smr.materials; } /// <summary> /// 换装(换1件到多件) /// </summary> /// <param name="avatarStr"></param> public void Inivatar(string[,] avatarStr) { int nLength = avatarStr.GetLength(0); for (int i = 0; i < nLength; i++) { ChangeMesh(avatarStr[i, 0], avatarStr[i, 1]); } } }