捏脸的两种方式(重点骨骼法)

本文介绍了Unity中捏脸的骨骼法,包括根据骨骼调节滑杆生成模型变换、骨骼与关键帧的关联、数据处理和转换。讨论了骨骼法与BlendShape的优缺点,强调骨骼法的可控性和数据效率,同时分享了处理捏脸数据和优化性能的技巧,如BakeMesh方法的应用。
摘要由CSDN通过智能技术生成

制作简述
1.根据骨骼分类表生成所有的调节滑杆, 并从预置的文件加载滑杆的默认值集合

2.如果滑杆值变了, 查分类表得到骨骼名(可能多个), 再根据骨骼名查关键帧表得到关键帧集合, 根据滑杆值插值出Local Transform

3.使用代码逻辑把老的Transform数据转换成新骨架能用的骨骼Transform

4.把骨骼Transform全部更新到模型上

捏脸有两种做法,一种是利用骨骼变换,一种是利用Blend Shape。

骨骼法是在脸的内部正常建立骨骼并蒙皮,并利用骨骼的缩放系数,位移来改变脸的外形。但由于是数学计算的结果,设计时难以直接对最终效果进行调整。

BlendShape则是正常做多个种类的脸型并离线出差异数据,设计的时候比较简单,但叠加的时候也不太好控制,而且数据量较大。

由于现在游戏都需要利用BlendShape来实现人物的表情,重叠的BlendShape不易处理。而骨骼法只是制作上麻烦点,但可控性较高,而且数据量也小,所以大部分游戏都是用骨骼来实现捏脸的。
骨骼的设计是唯一的难点

具体怎么布置骨骼可参考上图,其实并不需要太多的控制项,更细节的可动部分(比如口型和眼睛)是交给BlendShape完成的,骨骼仅仅用来布置捏脸需要变化的部分。

通常会在正常的骨骼上加上一个Position(0,0,0),Scale(1,1,1)的节点,然后让它代替父节点进行蒙皮,并把它作为捏脸时的可变数据。这样数值是单位化的,捏脸时容易处理。不希望缩放参数影响到子节点的时候也可以这样做。

这样直接改Bone的Transform数值就能看到变化了。

相比脸型,眼睛需要的节点数更多,因为需要针对眼球等多个物体处理,眼角长度和上挑都要可控,是捏脸骨骼最复杂的部分。

让捏脸变得人性化

虽然提供全部可变骨骼就能做出任何一种脸型,但那样只会让玩家轻易捏出怪物来。

通常的做法是给出一组可调整值的数值,对应骨骼的一个或者多个单位数值,让玩家在0-1之间选择。 

至于这些调整数值背后的逻辑——

我选择让一个调整项同时影响多个骨骼数据,每个骨骼数据只影响某条骨骼的某个值,并且可以指定动画曲线,以应对弧面上的位移。

通过组合就可以应对各种情况(眼睛这些地方必然需要影响多个骨骼)。

将Value值调整到某个极值,然后修改Min,Max查看效果,修改Curve曲线处理中间状况,生成捏脸数据的过程还是比较直观的。设计好之后,将序列化的数据存储起来,以后要用的时候载入并只允许修改Value的值,就可以应用在游戏的捏脸部分了。

而且这个编辑器的实现也是非常简单的,利用Unity自己的数据序列化面板就可以了。

public enum ModifyType

   {

       ScaleX,

       ScaleY,

       ScaleZ,

       X,

       Y,

       Z

   }

   [System.Serializable]

   public class ModifyDataGroup

   {

       public string name;

       [Range(0,1)]

       public float value = 0.5f;

       public ModifyData[] modifys;

   }

 

   [System.Serializable]

   public class ModifyData

   {

       public string name;

       public ModifyType type;

       public float min;

       public float max;

       public AnimationCurve curve;

   }

   public ModifyDataGroup[] modifyDataGroup;


去掉捏脸用的无用数据

很显然,我们为了实现捏脸加了许多没用的骨骼数据,这些都会影响到游戏运行时的效能。虽然量并不是很大,但要移除也并不困难。

如果不考虑BlendShape,其实只需要调用Unity的BakeMesh方法,替换Mesh并删掉骨骼就可以了。

但如果有BlendShape,Bake后的Mesh数据应用BlendShape后,会和以前有微量的偏移。这是因为BlendShape是在骨骼变化前先应用的,而Bake后,相当于是在骨骼变化后应用。

两者的差异和骨骼的变化强度有关,也和BlendShape的改变幅度有关,但确实在通常情况下差异不大(第三幅图是前两幅图的叠加,可以看到在脸部表情影响到的部分产生了微量的偏移)

但是即使少也是存在的。

解决方法是先将每一个BlendShape分别应用到Mesh上,再进行骨骼变换,蒙皮生成网格数据,然后再减掉Bake后的Mesh,重新生成一个新的BlendShape。

这其实相当于重做了一次BlendShape的生成过程(两个模型间求差值),数据就是完全准确的了。

下面的代码除了修正BlendShape外,还有蒙皮网格烘焙的代码实现。

public static Mesh BakeMesh(SkinnedMeshRenderer source)

   {

       Mesh target = Object.Instantiate(source.sharedMesh);

       int vertexCount = source.sharedMesh.vertexCount;

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Batman1208

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值