这里的分块Skin Combine指的是,把零散的skin mesh renderer组建,合并为若干块
比如我有15块skin,现在想合并为头和body两块,当然,网上的教程一般是无法实现的,
目前网上的都是合并为一块,但是对于低模可能不错,中模以上外加Blendshaps就完全GG了,这里需要一点骚操作;
我们合并的目的是,把含表情(Blendshaps)的skin独立,这里就是头,包含眼睛,舌头等等
把Blendshaps独立出,在一个相对顶点数较少的skin里的意义非常重大,因为,Unity的Blendshaps是非常呆笨的,他会在Blendshaps更新的时候,更新Blendshaps所在skin的mesh的所有顶点偏移,即使是这个顶点没有移动也会计算!这里性能开销很大!重复三遍。所以,聪明的任天堂公司,就没有使用fbx自带的Blendshaps功能,而是自定义Blendshaps功能,也非常简单,就是获取目标mesh的pose,然后对原版的mesh进行插值到目标mesh,这样可以有效减少顶点的计算!!因为,老任只需要计算部分需要更新的顶点即可,在初始化的时候安排一下即可!甚至还不需要用skin,用mesh即可,甚至这个都不需要,初始化取得Vector3[]数组后,直接Destroy都可以
性能大大提高!
如下:
ffggfg.PNG
表情这里我们一般来说,只取最后一帧数据,也就是说,从0-100是靠liner插值实现,所以你可以用Vector3[]
读取保存,之后重建Blendshaps也so easy,也可以通过bakedmesh函数实现mesh拷贝,第二个参数写ture
public SkinnedMeshRenderer[] SMR1, SMR2;
public Transform RootBone;
private HumanBone[] humanBones;
// Start is called before the first frame update
void Start()
{
humanBones= CreateHumanBone(out Dictionary<HumanBodyBones, Transform> boneMap);
CombineSkin(SMR1,this.gameObject,0);
CombineSkin(SMR2, this.gameObject,1);
//CombineSkin(this.gameObject);
GenericAvatar(humanBones, boneMap,out Avatar avatar,out Animator ani);
}
详细的代码不解释,GenericAvatar的代码可以git搜mmd for unity查看里面的实现,一模一样,这里SMR1, SMR2两个数组就是我们需要合并的内容,拉进去,注意需要把所有的skin都拉到这两个或多个SMRX里,否则后面会skin丢失!
然后这个CombineSkin()函数就是网上的普通的合并mesh的函数,只是,我们这里合并部分mesh而已
当然CombineSkin的多少取决于你,你也可以遍历判断表情在哪个skin,动态解析
或者,以65k顶点数为一组进行合并,在Unity2017.3及以后,单mesh 65k的限制没有了,大概支持65x2k的顶点数应该够用了吧
你可以这样:
#if UNITY_2017_3_OR_NEWER
//print("vertexCounter:"+ vertexCounter);
if (vertexCounter> 65535)
r.sharedMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
#else
throw new NotImplementedException(String.Format("exceed 65535 vertices: {0}", integrator.Positions.Count.ToString()));
#endif
最后一步GenericAvatar,顾名思义,就是重建Avatar,这个需要huomanoid bone,我们可以合并前,通过anim.GetBoneTransform(h_bone)获取,最后重新对Animator的Avatar赋值即可实现
还有一些技术细节比如T-POSE这些你们就自己解决吧,不难
合并前:
fsdsdf.PNG
合并后:
dfsdfsdg.PNG
这里,怎么说,其实你有单独的骨架fbx,那么你不必做一步GenericAvatar,这一步并不是必须的,但是对于没有单独骨架的模型,就是需要的,或许是我代码结构不对,另外,还有一种技术可以不必GenericAvatar,就是把所有的骨骼名字通过GetBoneTransform这个函数,映射到标准人形骨骼名字,Unity会自动识别
网友评论