Live2D_2.X基本功能

Live2D学习

是一种使用一系列连续的2d图像让图像看起像3d风格的绘图渲染技术。

在MyChild中的主人公就使用了该技术来实现一系列动作。非常适合需要不同方法与主角互动的游戏。

游戏中主人公的玩耍,吃饭 ,睡觉一系列动作以及鼠标点击主角和跟随鼠标转动等互动操作。

Live2DSDK环境配置:

Live2D.init(); //初始化(只在最初调用一次)

//Live2D.dispose(); //释放live2d占用的资源

加载模型:

1.直接加载模型

Live2DModelUnity.loadModel(Application.dataPath + "/Resources/Model/Epsilon/runtime/Epsilon.moc");//读取模型(加载moc文件后缀moc一定要)

2.通过二进制文件加载

将moc文件复制一份并将后缀上加上.bytes

 

TextAsset mocFile = Resources.Load("Model/Epsilon/runtime/Epsilon.moc");

Live2DModelUnity.loadModel(mocFile.bytes);

加载贴图:

和加载模型同理加载贴图。

live2dModel.setTexture("贴图索引" , ”贴图资源“);

显示模型:

private Matrix4x4 live2DCanvasPos; //可理解为画布位置    
指定显示位置和尺寸(使用正交矩阵与相关API显示图像,在由游戏物体的位置和摄像机的size调整图像到合适的位置)
float modelWidth = live2dModel.getCanvasWidth();
//正交投影矩阵
live2DCanvasPos = Matrix4x4.Ortho(0, modelWidth, modelWidth, 0, -50, 50);

之后就是在update中设置模型显示位置

    //设置模型显示位置
    live2dModel.setMatrix(transform.localToWorldMatrix * live2DCanvasPos);
    live2dModel.update();//更新模型可以更新的任何信息

最后

private void OnRenderObject()
{
    live2dModel.draw();  //显示模型
}

模型贴图加载之后,就是让它动起来。

加载动作源文件:

可public出去直接拖上去,也可以代码加载。

将动作源文件加载成Live2DMotion类型的动作。

public TextAsset[] motionFiles; //动作源文件
private Live2DMotion[] motions; //加载源文件之后的动作
motions = new Live2DMotion[motionFiles.Length];
//通过加载源文件来加载动作
for (int i = 0; i < motions.Length; i++)
{
    motions[i] = Live2DMotion.loadMotion(motionFiles[i].bytes);
}

动作播放方式API:

motions[0].setLoopFadeIn(false);//重复播放是否淡入 motions[0].setFadeOut(1000);//设置淡出时间(毫秒) motions[0].setFadeIn(1000); //设置淡入时间 motions[0].setLoop(true); //动画是否循环播放

启动动作播放:

动作播放需要动作管理者类

motionQueueManger = new MotionQueueManager();

motionQueueManger.startMotion(motions[0]);

然后在update中指定哪个模型显示该动作、动作的播放对应模型。

motionQueueManger.updateParam(live2dModel);

多个动作同时播放:

需要多个动作管理者MotionQueueManager来管理不同的动作。

motionQueueMangerA = new MotionQueueManager();

motionQueueMangerA.startMotion(motions[5]);

motionQueueMangerA.updateParam(live2dModel);

动作播放的优先级:

//优先级设置的标准:
//1.动作未进行的状态,优先级为0;(无任何动作或者所有动作都执行完毕)
//2.待机动作发生时,优先级为1;
//3.其他动作发生时,优先级为2;
//4.无视优先级,强制发生的动作,优先级为3;
private L2DMotionManager l2DMotionManager; //加入了优先级设置标准其它与MotionQueueManager无异private void Update()
{ 
    //判断待机动作
    if (l2DMotionManager.isFinished())
    {
        StartMotion(0, 1);
    }
    else if (Input.GetKeyDown(KeyCode.M))
    {
        StartMotion(14, 2);
    }
    l2DMotionManager.updateParam(live2dModel);
}
​
    public void StartMotion(int motionIndex , int priority)
    {
        if (l2DMotionManager.getCurrentPriority() >= priority)
        {
            return;
        }
​
        l2DMotionManager.startMotion(motions[motionIndex]);
    }

模型参数的设置:

通过改变模型的某个部位的参数来达到模型行为的改变

 

Live2D_2.X基本功能_第1张图片

 

    //设置参数
    live2dModel.setParamFloat("PARAM_EYE_R_OPEN" , 0 , 1 ); //ID , value , priority
    live2dModel.addToParamFloat("PARAM_EYE_R_OPEN", -0.1f, 1);//数值的累加
    live2dModel.multParamFloat("PARAM_EYE_R_OPEN", -0.1f, 1);//数值乘法
​
     通过获取索引去设置参数
     int paramAngleX;
     paramAngleX = live2dModel.getParamIndex("PARAM_EYE_R_OPEN");
     live2dModel.setParamFloat(paramAngleX, 30);
​
     //参数的保存和回复
     live2dModel.setParamFloat("PARAM_EYE_R_OPEN", 0, 1);
     //保存与回复的参数是整个模型的所有参数,并不只是之前同方法里设置的某几个参数
     live2dModel.saveParam();
     live2dModel.loadParam();
​
     //设定模型某一部分的透明度
     live2dModel.setPartsOpacity("PARTS_01_HAIR_SIDE_002", 0);
    //"PARTS_01_HAIR_SIDE_002"参数是part 不是param

这是param

Live2D_2.X基本功能_第2张图片

 

这是part

Live2D_2.X基本功能_第3张图片

 

使用参数设置也可以让模型动起来,所以我认为一般应该是使用这些参数来设置。

一般模型师会给你配置表中会有这些ID,以及数值设置。

自动眨眼:

    //auto眨眼
    private EyeBlinkMotion eyeBlinkMotion;
    eyeBlinkMotion = new EyeBlinkMotion();
    //眨眼
    eyeBlinkMotion.setParam(live2dModel);

跟随鼠标转动:

    //鼠标拖拽引起的动作变化
    private L2DTargetPoint drag;
    //拖拽
    drag = new L2DTargetPoint();
​
    //模型跟随鼠标转向
    Vector3 pos = Input.mousePosition;//屏幕坐标
​
    if (Input.GetMouseButton(0))
    {
        //设定屏幕坐标点 
        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();
​
    //模型转向
    if (drag.getX() != 0)
    {
        //设置身体眼睛头部跟随鼠标
        //如果想让眼睛一直看着你 在drag.getX()前加"-"号
        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", 1 * -drag.getX());
        live2dModel.setParamFloat("PARAM_EYE_BALL_X" , -drag.getY());
    }
//得到的live2d鼠标检测点的比例值是-1到1(对应一个live2d拖拽)
//管理坐标系,或者叫影响度
//然后我们通过这个值去设置我们的参数,比如旋转30度*当前得到的值

Live2D物理系统

头发的摆动

根据模型的不同头发的参数也不同。demo里的模型头发分为前左侧,前有侧,后左侧,后右侧。所以,我们需要每个部分都进行操作。

首先定义Live2D插件中关于头发的类型

private PhysicsHair physicsHairSide_L; //前左侧发
private PhysicsHair physicsHairSide_R; //前右侧发
private PhysicsHair physicsHairBack_L;  //左后发
private PhysicsHair physicsHairBack_R;  //左后发

在Start中设置好各种参数

  1. private void HairMotion()
    {
       //头发的摇摆
       physicsHairSide_L = new PhysicsHair();
       physicsHairSide_R = new PhysicsHair();
       physicsHairBack_L = new PhysicsHair();
       physicsHairBack_R = new PhysicsHair();
       //套用物理运算,让头发动起来
       physicsHairSide_L.setup(0.2f, 0.5f, 0.14f); //长度(影响摇摆周期,越长越慢,反之) 空气阻力: 可设定0-1的值。预设值是0.5 重量 kg
       physicsHairSide_R.setup(0.2f, 0.5f, 0.14f);   
       physicsHairBack_L.setup(0.7f, 0.5f, 0.14f); //长度(影响摇摆周期,越长越慢,反之) 空气阻力: 可设定0-1的值。预设值是0.5 重量 kg
       physicsHairBack_R.setup(0.7f, 0.5f, 0.14f);
      
       //设置输入参数
       //设置哪一部分变动时进行哪一种运算
       PhysicsHair.Src srcX_L = PhysicsHair.Src.SRC_TO_X; //横向摇摆
       //PhysicsHair.Src srcX_L = PhysicsHair.Src.SRC_TO_G_ANGLE; //下垂
       PhysicsHair.Src srcX_R = PhysicsHair.Src.SRC_TO_X; //效果和下垂差不多
       PhysicsHair.Src srcZ = PhysicsHair.Src.SRC_TO_G_ANGLE;
      
       //第三个参数 , 当PARAM_ANGLE_X变动时,头发受到0.005倍的影响度
       physicsHairSide_L.addSrcParam(srcX_L, "PARAM_ANGLE_X", 0.005f, 1);
       physicsHairSide_R.addSrcParam(srcX_R, "PARAM_ANGLE_X", 0.005f, 1);
      
       physicsHairBack_L.addSrcParam(srcX_L, "PARAM_ANGLE_X", 0.005f, 1);
       physicsHairBack_R.addSrcParam(srcX_R, "PARAM_ANGLE_X", 0.005f, 1);
       physicsHairBack_L.addSrcParam(srcZ, "PARAM_ANGLE_Z", 0.8f, 1);
       physicsHairBack_R.addSrcParam(srcZ, "PARAM_ANGLE_Z", 0.8f, 1);
      
       //设置输出表现
       PhysicsHair.Target target = PhysicsHair.Target.TARGET_FROM_ANGLE;//表现形式
      
       physicsHairSide_L.addTargetParam(target, "PARAM_HAIR_SIDE_L", 0.005f, 1);
       physicsHairSide_R.addTargetParam(target, "PARAM_HAIR_SIDE_R", 0.005f, 1);
      
       physicsHairBack_L.addTargetParam(target, "PARAM_HAIR_BACK_L", 0.005f, 1);
       physicsHairBack_R.addTargetParam(target, "PARAM_HAIR_BACK_R", 0.005f, 1);
    }

最后在update中更新头发动作就完成了

    //更新头发动作
    long time = UtSystem.getSystemTimeMSec(); //执行时间(一定要是long类型,具体是什么时间我忘记了)
​
    physicsHairSide_L.update(live2dModel, time);
    physicsHairSide_R.update(live2dModel, time);
​
    physicsHairBack_L.update(live2dModel, time);
    physicsHairBack_R.update(live2dModel, time);

表情系统

/// 
/// 加载表情动作
/// 
private void ExpressionMotion()
{
    ExpressionMotionMgr = new MotionQueueManager();
​
    expressions = new L2DExpressionMotion[expressionFiles.Length];
​
    for (int i = 0; i < expressions.Length; i++)
    {
        expressions[i] = L2DExpressionMotion.loadJson(expressionFiles[i].bytes);
    }
}
​
    /// 
    /// 播放表情
    /// 
    private void PlayExpression()
    {
        if (Input.GetKeyDown(KeyCode.M))
        {
            motionIndex++;
            if (motionIndex >= expressions.Length)
            {
                motionIndex = 0;
            }
            ExpressionMotionMgr.startMotion(expressions[motionIndex]);
        }
​
        ExpressionMotionMgr.updateParam(live2dModel);
    }

将口型动作做成moc动作文件

1.播放声音时播放动作。

2.如果是Android/IOS项目,从他SDK中获取到声音,根据声音的波频来设置嘴长的大小。

 

 

 

3.X

你可能感兴趣的:(Unity)