[Unity实战]详解换装系统(三)

在阅读本文章之前,本人强烈建议你先看看本系列的前两篇文章,对换装系统有一些了解后再继续!

在上一篇文章中,运行之后是这样的:

我们的target上挂上各种类型的mesh,而每一个mesh上都有一个Skinned Mesh Renderer组件,这无疑会增加运算量,根据官方demo的指引,我们应该合并mesh,这样target上就只有一个Skinned Mesh Renderer组件,从而达到优化的目的!

本人对上一篇文章的代码进行了一些修改,主要是添加了6处新的代码,并对不需要的代码进行了注释(不删除),方便了理解。

其实跟上一篇文章的代码差别不太大。上一篇文章是针对target下的单个部位更换mesh,绑定骨架。而这片文章是先把target需要的所有部件的mesh、材质、骨架全部存放好,再一次性的赋给target下唯一的Skinned Mesh Renderer。

代码如下:

using UnityEngine;using System.Collections;using System.Collections.Generic;public class AvatarSys2 : MonoBehaviour{public static AvatarSys2 instance;//来源模型private Transform source;//目标骨架private Transform target;//存放来源模型的信息,分别为部位名字,部位编号,部位的SkinnedMeshRenderer组件//根据部位名字,部位编号取得想要的部位private Dictionary<string, Dictionary<string, SkinnedMeshRenderer>> sourceData =new Dictionary<string, Dictionary<string, SkinnedMeshRenderer>>();//new 01SkinnedMeshRenderer targetSmr;//target上只有一个SkinnedMeshRenderer组件List<CombineInstance> combineInstances = new List<CombineInstance>();//存放target上的所有meshList<Material> materials = new List<Material>();//存放target上的所有materialList<Transform> bones = new List<Transform>();//存放target上的所有bone////存放目标骨架的信息,分别为部位名字,部位上的SkinnedMeshRenderer组件////没有编号是因为target上只有一套//private Dictionary<string, SkinnedMeshRenderer> targetSmr =// new Dictionary<string, SkinnedMeshRenderer>();//存放目标骨架的骨架信息,,用于mesh绑定骨架private Transform[] hips;//部位信息,目标骨架初始化为模型时需要的部位,注意命名是依据来源模型上的部位命名的public string[,] avatarStr = new string[,]{{"face","1"},{"hair","1"},{"pants","1"},{"shoes","1"},{"top","1"}};// Use this for initializationvoid Start(){instance = this;InstantiateSource();//实例化来源模型InstantiateTarget();//实例化目标骨架SaveData();//存储来源模型和目标骨架的信息InitAvatar();//将目标骨架初始化为模型target.animation.PlayQueued("walk");}void InstantiateSource(){GameObject sourceObj = Instantiate(Resources.Load("Source")) as GameObject;source = sourceObj.transform;sourceObj.SetActive(false);}void InstantiateTarget(){GameObject targetObj = Instantiate(Resources.Load("Target")) as GameObject;target = targetObj.transform;hips = target.GetComponentsInChildren<Transform>();//new 02targetSmr = target.gameObject.AddComponent<SkinnedMeshRenderer>();}void SaveData(){if ((source == null) || (target == null))return;SkinnedMeshRenderer[] parts = source.GetComponentsInChildren<SkinnedMeshRenderer>(true);//true表示把隐藏部位的组件也获得foreach (SkinnedMeshRenderer part in parts){string[] partName = part.name.Split('-');if (!sourceData.ContainsKey(partName[0]))//每有一种新类型的部位{////每有一种新类型的部位就在骨架下生成一个空GameObject//GameObject partobj = new GameObject();//partobj.name = partName[0];//partobj.transform.parent = target;//部位类型只记录一次sourceData.Add(partName[0], new Dictionary<string, SkinnedMeshRenderer>());////targetSmr只记录一套部位的信息,例如裤子有两套模型,只记录一套的////因为target是用来展示的,各种部位只要一套即可//targetSmr.Add(partName[0], partobj.AddComponent<SkinnedMeshRenderer>());}//sourceData记录所有部位信息sourceData[partName[0]].Add(partName[1], part);}}public void ChangeMesh(string part, string num)//传入部位名字,编号{//因为sourceData记录所有部位信息,所以可以查找到所要的新的部位SkinnedMeshRenderer smr = sourceData[part][num];//List<Transform> bones = new List<Transform>();//根据新的部位绑定的骨架信息,在target的骨架上找到相应的位置//例如头发mesh,在source中它绑定在脑袋上,那么我们在target上也要找到脑袋这个位置foreach (Transform bone in smr.bones){foreach (Transform hip in hips){if (hip.name == bone.name){bones.Add(hip);break;}}}//targetSmr[part].materials = smr.materials;//更换材质//targetSmr[part].sharedMesh = smr.sharedMesh;//更换mesh//targetSmr[part].bones = bones.ToArray();//将mesh绑定到合适的骨架中//new 03CombineInstance ci = new CombineInstance();ci.mesh = smr.sharedMesh;combineInstances.Add(ci);materials.AddRange(smr.materials);}//new 04public void InitAvatar(){Empty();int length = avatarStr.GetLength(0);for (int i = 0; i < length; i++){ChangeMesh(avatarStr[i, 0], avatarStr[i, 1]);}Combine();}//new 05void Empty(){combineInstances.Clear();materials.Clear();bones.Clear();}//new 06void Combine(){targetSmr.sharedMesh = new Mesh();targetSmr.sharedMesh.CombineMeshes(combineInstances.ToArray(),false,false);targetSmr.materials = materials.ToArray();targetSmr.bones = bones.ToArray();}}运行后:

怎么样?很酷吧!

积极的人在每一次忧患中都看到一个机会,而消极的人则在每个机会都看到某种忧患。

[Unity实战]详解换装系统(三)

相关文章:

你感兴趣的文章:

标签云: