前两天重装了 CV VTuber Example,正好借机介绍一些常用的让卡通人物更可爱的方法。
我们将在 CV VTuber Example 提供的 VRMCVVTuber 基础上进行开发。在 AssetsCVVTuberExampleCVVTuberAddons 中双击 VRMCVVTuber.unitypackage 导入。
VRMCVVTuber 展示了如何将在 CV Vtuber 项目中使用 VRM 模型。如果你不知道 VRM 是什么,可以参考这里。
除了 VRMCVVTuber.unitypackage 之外,我们还需要导入 UniVRM 以及我们的老朋友 AliciaSolid,同样可以参考上面的文章。全部导入后,打开 VRMCVVTuberExample,拖入 AliciaSolid,进行相应设置后我们的 AliciaSolid 就会跟着摄像头里的人脸动起来了。
缩小 FOV
Unity 中相机的默认 FOV 是 60,但是对于以近景卡通人物为主的场景来说,这个 FOV 太突出立体感,容易引起脸部的变形。比较适合的 FOV 为 14 以下,下图左侧为 14,右侧为 60,区别一目了然。
注视相机
这里我们将利用 VRM 提供的注视相机的功能。点开 AliciaSolid 的 VRMLookAtHead 组件,将其中的 Target 设为我们的相机。同时注意 VRMLookAtBoneApplyer (请忽略日本开发者的拼写错误)中左右眼的骨骼有否设置正确。
另外需要将 AliciaSolid 中眼睛的骨骼重新调整层次,从下图
改为下图
以确保眼部高光跟随眼睛一起动。
启动程序,是不是已经有点明星相了。
上半身联动
根据日本人的理论,男性头部转动时上半身静止,女性则是连带肩膀上半身一起动,
来源:https://togetter.com/li/929420
其实也可以想象,女孩子嘛扭扭捏捏总会显得可爱一点。
要实现这个效果,我们可以让上半身骨骼与头部骨骼联动。不过 CV Vtuber Example 中为我们提供了类似功能。打开 VRMHeadRotationController 对象,点开其中的 HeadRotationController 组件,勾选其中的 Invert Y Axis,让身体和头朝相反方向运动。
怎么样,是不是做作点了。:)
加入呼吸
就像我们需要一个 idle 动画让人物不要完全处于静止状态一样,静止时加入模拟呼吸的动作也会让人物显得更为鲜活。在下面的连接可以下载到现成的呼吸代码。
http://mebiustos.hatenablog.com/entry/2015/08/31/201902
点击网页的这个部分下载。
将下载得到的 unitypackage 导入项目,并将其中的 BreathController 添加到 AliciaSolid 对象上。
BreathController 可以自动针对 Humanoid 模型添加呼吸功能,其中会用到 head,neck,chest,spine 四根骨骼,因为 AliciaSolid 没有设置 chest, BreathController 需要做些修改,这里不详述啦。修正 BreathController,启动程序就能看到效果。为了让呼吸更明显,这里没有加入人脸识别部分。
微眼动
人的眼球在注视时发生着轻微的运动,这一现象称为 Saccade。 https://en.wikipedia.org/wiki/Saccade
这里有一段现成的代码模拟了这个现象。
https://gist.github.com/GOROman/51ee32887bd1d3248b7610f845904b30
将代码加入项目中并且为 AliciaSolid 对象的眼睛以及高光添加 EyeJitter 组件。
启动工程,可以看到微眼动效果,这里同样关闭了人脸识别部分。
改眨眼为笑颜
最后这个有点赖皮。要可爱当然得经常笑啦,所以我们把闭眼时的 blendshape 改为微笑,并且降低判断闭眼的阈值,让微笑出现的更频繁。修改 VRMFaceBlendShapeController 的 UpdateFaceAnimation 函数如下,
if (enableEye) {
float eyeOpen = (GetLeftEyeOpenRatio (points) + GetRightEyeOpenRatio (points)) / 2.0f;
//Debug.Log("eyeOpen " + eyeOpen);
if (eyeOpen >= 0.1f) {
eyeOpen = 1.0f;
} else {
eyeOpen = 0.0f;
}
EyeParam = Mathf.Lerp (EyeParam, 1.0f - eyeOpen, eyeLeapT);
blendShapeProxy.AccumulateValue (BlendShapePreset.Joy, EyeParam);
}
最后上一个最终成果。是不是比开始时可爱些了?
写到这里发现眨眼其实还有可以改善的地方,下次有机会再说吧。