梦 罟
Live2DSdkforUnity
明天就开学了……虽然是上网课但也算是开学吧。总结这个寒假,自己好像也没干什么事= =最后把SDK做完吧。
嘴型变化
相比于SDK2,SDK4框架中内置了根据音频来自动判断嘴巴开合的方法,这极大地提高了live2d的互动性和真实性,而且简单易行。首先我们需要在预制体上挂载Cubism Mouth Controller、Cubism Auido Mouth Input以及Audio Source三个组件;然后在parameters中找到控制嘴巴开合的参数(PARAM_Mouth_OpenY),挂载Cubism Mouth Parameter组件;最后在Audio Source中添加对应的语音片段,点击播放,就可以看见嘴型的变化。
播放动作
前面已经提到,在Live2d模型中通常会有motion.json的动作文件;挂载了SDK后,这些.json文件会被转化为Unity可以识别的.anim文件,即我们所说的AnimationClip。使用Unity的动画控制机打开即可实现动作的播放。
当然,SDK还提供了另外一种动画播放方式。在预制体上挂载Cubism Motion Controller和Cubism fade Controller,接着只需要在我们编写的脚本中添加 Live2D.Cubism.Framework.Motion的命名空间,就可以在脚本中利用CubismMotionController来实现对动画的管理。这里介绍几个重要的API:
1.PlayAnimation(AnimationClip clip, int layerIndex = 0, int priority = CubismMotionPriority.PriorityNormal, bool isLoop = true, float speed = 1.0f);
这个API实现的是动画播放,其中第一个参数为要播放的动画片段;第二个参数是Cubism动画控制机的层数,一般默认为0;第三个参数是动画的层级,这里我们追溯它的定义,发现框架中这样定义层级:
第一层为无优先权,代号为0;第二层是待机动画的层级,即Idle动画,代号为1;第三层是一般的动画;第四层则为强制播放;根据实践经验来看,除了idle动画默认为1,其余情况大多可用默认值2来完成。第四个 参数是是否循环播放,一个布尔类型的变量;最后一个参数是播放速度,不做解释说明。
2.StopAnimation(int animationIndex, int layerIndex = 0)
显然这个API的作用是停止某个动画的播放。第一个参数是停播动画所在的Index;第二个参数是控制机的图层,默认为零。
3.StopAllAnimation()
停止播放所有动画,无参数输入,不做解释。
命中判断
在live2d展示中,往往我们点击模型的不同部位,模型会做出不同的动作;完成此功能的前提条件是对点击进行识别。在SDK4中提供了Cubism Raycaster的组件来实现点击识别。我们可以编辑这样一组脚本来实现对命中部位的查看:
using UnityEngine;
using Live2D.Cubism.Framework.Raycasting;
using Live2D.Cubism.Framework.Motion;
public class CubismHitTest : MonoBehaviour
{
private void Update()
{
// Return early in case of no user interaction.
if (!Input.GetMouseButtonDown(0))
{
return;
}
var raycaster = GetComponent();
// Get up to 4 results of collision detection.
var results = new CubismRaycastHit[4];
// Cast ray from pointer position.
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
var hitCount = raycaster.Raycast(ray, results);
// Show results.
var resultsText = hitCount.ToString();
for (var i = 0; i < hitCount; i++)
{
resultsText += "n" + results[i].Drawable.name;
}
Debug.Log(resultsText);
}
}
该脚本的作用是识别鼠标点击的部分,并将其名称返回到Console中,点击效果如图所示:
动作切换
当然,命中判断不是最目的,最终目的是实现动作切换,完成live2d整个互动系统的组装。由于官方没有提供对应的组件,所以我考虑将命中判断和动画组件的两个功能结合,通过命中判断来控制动画的播放。在动作切换中药一定要注意对动画的层级设置。本文提供自制的脚本供大家来参考:
using Live2D.Cubism.Framework.Motion;
using UnityEngine;
using Live2D.Cubism.Framework.Raycasting;
public class Touchmotion: MonoBehaviour
{
CubismMotionController _motionController;
public AnimationClip[] animationclip;
private void Start()
{
_motionController = GetComponent();
}
public void PlayMotion(AnimationClip animation)
{
if ((_motionController == null) || (animation == null))
{
return;
}
_motionController.PlayAnimation(animation, isLoop: false);
}
private void Update()
{
_motionController.PlayAnimation(animationclip[3], 0, 1, isLoop: true);
// Return early in case of no user interaction.
if (!Input.GetMouseButtonDown(0))
{
return;
}
var raycaster = GetComponent();
// Get up to 4 results of collision detection.
var results = new CubismRaycastHit[4];
// Cast ray from pointer position.
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
var hitCount = raycaster.Raycast(ray, results);
// Show results.
var resultsText = hitCount.ToString();
for (var i = 0; i < hitCount; i++)
{
resultsText += "n" + results[i].Drawable.name;
}
if (resultsText == "2nTouchSpecialnTouchBody")
{
_motionController.PlayAnimation(animationclip[0], isLoop: false);
}
else if (resultsText=="1nTouchBody")
{
_motionController.PlayAnimation(animationclip[1], isLoop: false);
}
else if (resultsText == "1nTouchHead")
{
_motionController.PlayAnimation(animationclip[2], isLoop: false);
}
}
}
至此,一个live2d模型的基本功能已经实现完毕,该有的互动系统也已经完成。至于如何利用live2d模型来完成一些游戏、动画的制作,还需要读者的自行理解考虑。当然,也欢迎在公众号后台中交流~
文/lost_Ink