Unity换装系统 第一篇
Darren原创.欢迎转载,转载请注明出处.
这几天在研究换装系统,现在将研究过程中的思路记录下来。
换装系统本人分两步来实现:
1本地换装以及换装编辑器
2换装资源规范制定,以及通过读取网络资源实现换装
今天先记录本地换装,换装的步骤为:
1.创建主骨架。
主骨架有两个方法获取到:
第一个方法是美术直接输出不带蒙皮的骨骼信息
第二个方法是美术输出带蒙皮的模型,将模型所有带SkinnedMeshRenderer的gameobject删掉,剩下的就是主骨架
_go = Instantiate(prefab) as GameObject;
foreach (SkinnedMeshRenderer item in _go.GetComponentsInChildren<SkinnedMeshRenderer>())
{
Object.DestroyImmediate(item.gameObject);
}
2.记录需要换装的部件中的所有 SkinnedMeshRenderer中的蒙皮信息,具体需要记录SkinnedMeshRenderer.bones,SkinnedMeshRenderer.sharedMaterials以及SkinnedMeshRenderer.sharedMesh
public struct AvtarInfo
{
public Dictionary<string, SkinMeshInfo> skmr;
}
private void _GetSkinMeshInfo(GameObject prefab, AvtarInfo avtarinfo)
{
foreach (SkinnedMeshRenderer item in prefab.GetComponentsInChildren<SkinnedMeshRenderer>(true))
{
List<string> bonesName = new List<string>();
for (int i = 0; i < item.bones.Length; i++)
{
bonesName.Add(item.bones[i].name);
}
SkinMeshInfo info = new SkinMeshInfo();
info.mesh = item.sharedMesh;
info.materials = new List<Material>();
info.bonesName = bonesName;
for (int i = 0; i < item.sharedMaterials.Length; i++)
{
info.materials.Add(Instantiate(item.sharedMaterials[i]) as Material);
}
avtarinfo.skmr.Add(item.name, info);
}
}
3。将所有换装的Mesh合并成一个Mesh,将所有骨骼合并成一个Transform数组,将所有部件中的materials
合并层一个合计。并将这些数据赋予主骨架物体上的SkinnedMeshRenderer上对应的成员变量
public struct SkinMeshInfo
{
public List<Material> materials;
public Mesh mesh;
public List<string> bonesName;
}
public GameObject Generate(GameObject root, Dictionary<string, SkinMeshInfo> _skmr)
{
float startTime = Time.realtimeSinceStartup;
List<CombineInstance> combineInstances = new List<CombineInstance>();
List<Material> materials = new List<Material>();
List<Transform> bones = new List<Transform>();
Transform[] transforms = root.GetComponentsInChildren<Transform>();
foreach (var item in _skmr)
{
for (int sub = 0; sub < item.Value.mesh.subMeshCount; sub++)
{
CombineInstance ci = new CombineInstance();
ci.mesh = it