基础传送门
Skinned Mesh Renderer:蒙皮网格渲染器
当导入有蒙皮的网格时,骨骼蒙皮渲染器会自动添加到加入的网络。
需要了解的:
Mesh:此渲染器使用的网格。
RootBone:动画“根”的骨骼(即所有其他骨骼相对于其移动的骨骼)。
Materials:所用材质。
换装原理:(使用Unity官方案例说明)
1.获取需要换装的每个部位以及SkinnedMeshRenderer
SkinnedMeshRenderer[] parts = souceTrans.GetComponentsInChildren<SkinnedMeshRenderer>(); // 遍历所有子物体有SkinnedMeshRenderer,进行存储
foreach (var part in parts)
{
string[] names = part.name.Split('-');
if (!data.ContainsKey(names[0]))
{
//每次遍历到一个新的部位
//骨骼下边生成对应的skm
GameObject partGo = new GameObject();
partGo.name = names[0];
partGo.transform.parent = target.transform;
smr.Add(names[0], partGo.AddComponent<SkinnedMeshRenderer>()); //把骨骼target身上的skm信息存储,部位只记录一次
data.Add(names[0], new Dictionary<string, SkinnedMeshRenderer>());
}
data[names[0]].Add(names[1], part); //存储所有的skm信息到数据里边
}
2.获取要替换SkinnedMeshRenderer
SkinnedMeshRenderer skm = data[part][num]; //要更换的部位
3.刷新骨骼
List<Transform> bones = new List<Transform>();
foreach (var trans in skm.bones)
{
foreach (var bone in hips)
{
if (bone.name == trans.name)
{
bones.Add(bone);
break;
}
}
}
4.进行替换
smr[part].bones = bones.ToArray(); //绑定骨骼
smr[part].materials = skm.materials; //替换材质
smr[part].sharedMesh = skm.sharedMesh; //更换mesh
这就是基础的算法,更高级的就是进行网格合并,减少Draw Call。
为此还可以专门封装一个需要换装部位的类:Part SMR
如下所示:
public class PartSMR
{
private GameObject gameObjet;
private SkinnedMeshRenderer smr;
Transform[] hips;
public PartSMR(GameObject go, Transform[] hips)
{
this.hips = hips;
gameObjet = go;
smr = go.GetComponent<SkinnedMeshRenderer>();
}
public void ChangeMesh(SkinnedMeshRenderer mr)
{
//取得相对应名称的骨架物件来建立新的骨架列表
List<Transform> bones = new List<Transform>();
foreach (Transform bone in mr.bones)
{
foreach (Transform hip in hips)
{
if (hip.name != bone.name) continue;
bones.Add(hip);
break;
}
}
smr.sharedMesh = mr.sharedMesh;
smr.bones = bones.ToArray();
smr.materials = mr.materials;
}
}
注意:
1.对骨骼修改时,要保证不能打乱节点的顺序。使用目标的骨骼数据做循环,保证骨骼节点的顺序。