说在前面
本文只是实例说明了最基础的换装思路:刷新骨骼
完整的换装系统需要涉及到:Mesh合并、刷新骨骼、材质合并
直接上效果
动态换装需要了解SkinnedMeshRenderer动画如何播放。
本质上是骨骼的运动,拖拽着Mesh的定点进行运动(一个定点会被多个骨骼按权重控制),以此形成动画。
骨骼在SkinnedMeshRenderer中是字段bones
,是一个Transform[]
,一般在模型中可以看到skeleton
节点下密密麻麻的骨骼,如下图
简单来说动态换装其实就是给衣服部件动态的替换骨骼,需要做的有两步:
- 收集骨骼(就是一堆TransForm)
- 将部件的骨骼挨个刷新
代码如下:
第一步
可以从Skeleton
为根节点通过GetComponentsInChildren<Transform>()
方式获取根节点下骨骼。
在实例中,我的这个模型中,根节点包含了头部(头部部件不是SkinnedMeshRenderer),比较特殊,所以从body(身子部分)的Mesh中获取骨骼,效果是一样的。
bonesDic = new Dictionary<string, Transform>();
SkinnedMeshRenderer bodySMR = transform.Find("body").GetComponent<SkinnedMeshRenderer>();
for (int i = 0; i < bodySMR.bones.Length; i++)
{
string boneName = bodySMR.bones[i].name;
Transform bone = bodySMR.bones[i];
if (!bonesDic.ContainsKey(boneName))
{
bonesDic.Add(boneName, bone);
}
}
第二步
将身体部件的骨骼替换成收集好的骨骼
因为部件只会涉及到部分骨骼,所以按照原有的骨骼名进行全部替换
其中partObj
就是要换装的部分
SkinnedMeshRenderer smr = partObj.GetComponent<SkinnedMeshRenderer>();
List<Transform> bones = new List<Transform>();
for (int i = 0; i < smr.bones.Length; i++)
{
string name = smr.bones[i].name;
if (bonesDic.ContainsKey(name))
{
bones.Add(bonesDic[name]);
}
}
smr.bones = bones.ToArray();
以上就是动态换装的思路
总的来说,以上方式实现换装很简单,可以实现效果,但是一般在工程中同时要考虑效率。这就涉及到mesh合并以及材质合并,这部分才是换装新系统的重要部分。