接下来实现模型自动眨眼的功能,这个很简单
定义一个眨眼对象
//自动眨眼
private EyeBlinkMotion eyeBlinkMotion;
接下来在start函数中实例化
//眨眼
eyeBlinkMotion = new EyeBlinkMotion();
在update函数中更新模型即可
void Update () {
//设置矩阵 两个矩阵相乘
//localToWorldMatrix局部转世界
live2DModel.setMatrix(transform.localToWorldMatrix * live2dCanvasPos );
eyeBlinkMotion.setParam(live2DModel);
live2DModel.update();
}
接下来是实现模型注视鼠标点击位置的功能
首先定义一个live2d的拖拽坐标系,模型的动作是根据这个拖拽坐标系中的值来决定的
//拖拽座标
private L2DTargetPoint drag;
实例化
//鼠标拖拽
drag = new L2DTargetPoint();
模型跟随鼠标转向与看向,Live2d鼠标检测值的范围是-1~1,这个值先当于权重,通过这个值去设置参数,旋转30度为 30*当前得到的值,drag.set就是将屏幕坐标映射到一个范围为-1~1的坐标 。得到drag值后使用之前的设置参数的方法。
在update函数中
Vector3 pos = Input.mousePosition; //屏幕坐标
if (Input.GetMouseButton(0))
{
//将屏幕坐标转换到live2d检测坐标
drag.Set(pos.x/ Screen.width * 2 - 1, pos.y / Screen.height * 2 - 1);
}//鼠标抬起
else if (Input.GetMouseButtonUp(0))
{
drag.Set(0, 0);
}
//参数更新,考虑加速度等元素,计算坐标,逐帧更新
drag.update();
//模型转向 为0时鼠标已经松开
if(drag.getX() != 0)
{
live2DModel.setParamFloat("PARAM_ANGLE_X", 30 * drag.getX());
live2DModel.setParamFloat("PARAM_ANGLE_Y", 30 * drag.getY());
live2DModel.setParamFloat("PARAM_BODY_ANGLE_X", 10 * drag.getX());
live2DModel.setParamFloat("PARAM_EYE_BALL_X", drag.getX());
live2DModel.setParamFloat("PARAM_EYE_BALL_Y", drag.getY());
//取负眼睛只盯着屏幕正中心
//live2DModel.setParamFloat("PARAM_EYE_BALL_X", -drag.getX());
//live2DModel.setParamFloat("PARAM_EYE_BALL_Y", -drag.getY());
}
这样模型就会盯向鼠标点击的位置,注意的是设置眼球的参数时,将值的参数设为负眼睛就会一直盯着屏幕正中间。
接下来实现人物发生动作时,头发随之甩动的物理效果。
用cubism打开人物cmox文件会发现模型头发分为四个部分,侧面两个头发,后面两个头发。
首先定义头发的物理系统
//物理系统的设定
//侧发
private PhysicsHair physicsHairSideLeft;
private PhysicsHair physicsHairSideRight;
//后面的头发
private PhysicsHair physicsHairBackLeft;
private PhysicsHair physicsHairBackRight;
举例一束头发的设置,剩下的是一样的
在start函数中,首先实例化
//头发摇摆
physicsHairSideLeft = new PhysicsHair();
接着设置头发的物理参数,其物理参数在模型文件夹的json文件中
第一个参数是头发长度,影响摇摆时间;第二个参数是空气阻力范围0~1;第三个是头发重量kg
physicsHairSideLeft.setup(0.2f,0.5f, 0.14f);
接着设置什么部位的运动会影响头发的运动
addSrcParam方法第一个参数是哪一种运算,第二是部位id,第三个参数PARAM_ANGLE_X改变时受到的影响度,第四个参数是参数权重 。PhysicsHair.Src有三个枚举, X是横向移动, SRC_TO_G_ANGLE/SRC_TO_Y是下垂
PhysicsHair.Src srcXLeft = PhysicsHair.Src.SRC_TO_X;
physicsHairSideLeft.addSrcParam(srcXLeft, "PARAM_ANGLE_X",0.005f,1f);
接着设置这个部位运动了影响的目标和形式
PhysicsHair.Target有两个枚举,其中后缀为V是使部件运动趋势呈v形变化
PhysicsHair.Target targetLeft = PhysicsHair.Target.TARGET_FROM_ANGLE;
physicsHairSideLeft.addTargetParam(targetLeft, "PARAM_HAIR_SIDE_L", 0.005f, 1);
接着在update函数中设定头发运动时间,接着更新头发状态即可
long time = UtSystem.getUserTimeMSec();//获取执行时间
//受力时间
physicsHairSideLeft.update(live2DModel,time);
头发就随之摆动了起来。
接下来做表情的切换
定义一个存储表情文件的textAsset数组,一个存储表情实体的L2DExpressionMotion对象数组,一个表情管理器
//表情
public TextAsset[] expressionFiles;
//表情实体
public L2DExpressionMotion[] expressions;
//表情管理
private MotionQueueManager expressionMotionQueueManager;
将Epsilon\runtime\expressions下的所有json文件从inspector面板拖入
这些json文件存储着表情的动作
在start函数中一一加载expressionFiles中存储着表情的json文件
expressionMotionQueueManager = new MotionQueueManager();
expressions = new L2DExpressionMotion[expressionFiles.Length];
for (int i = 0; i < expressions.Length; i++)
{
//加载表情
expressions[i] = L2DExpressionMotion.loadJson(expressionFiles[i].bytes);
}
定义一个索引index ,在update中更新这个index来悬着expression[i]中的表情即可
if (Input.GetKeyDown(KeyCode.M))
{
motionIndex++;
if (motionIndex >=expressions.Length)
{
motionIndex = 0;
}
expressionMotionQueueManager.startMotion(expressions[motionIndex]);
}
expressionMotionQueueManager.updateParam(live2DModel);
值得一提的这种表情切换方法会导致表情的叠加,比如在第四个表情【脸红】之后,所有表情都有脸红的状态。
直接使用官方给的live2d框架就不会导致这些问题。
2.x版本只学到这里。