1.Live2d的sdk接入与素材模型的导入

导入该素材模型和Live2d的sdk

Live2D模型制作到显示的基本流程:

1.初始化模型。
    
    1.制作模型(读取moc文件)。
    
    2.与贴图建立关联。
    
    3.与绘图环境建立链接。(有些平台不需要)。

4.制定显示位置与尺寸。

2.更新模型状态。

1.更新顶点。

2.绘图。

Live2d虚拟环境的初始化与模型读取的第一种方法

 void Start () {//初始化Live2D.init();//释放//Live2D.dispose();//读取模型Live2DModelUnity.loadModel(Application.dataPath + "/Resources/Epsilon/runtime/Epsilon.moc");}

以二进制形式去读取模型

现将素材的.moc文件添加后缀为.moc.bytes,然后在输入下面的代码

        TextAsset mocFile = Resources.Load<TextAsset>("Epsilon/runtime/Epsilon.moc");Live2DModelUnity.loadModel(mocFile.bytes);

模型与贴图建立关联(单张贴图)

        //与贴图建立关联Texture2D texture2D = Resources.Load<Texture2D>("");live2DModel.setTexture(0,texture2D);

多张贴图的设置方法

        //与多张贴图建立关联Texture2D texture2D1 = Resources.Load<Texture2D>("Epsilon/runtime/Epsilon.1024/texture_00");Texture2D texture2D2 = Resources.Load<Texture2D>("Epsilon/runtime/Epsilon.1024/texture_01");Texture2D texture2D3 = Resources.Load<Texture2D>("Epsilon/runtime/Epsilon.1024/texture_02");live2DModel.setTexture(0, texture2D1);live2DModel.setTexture(1, texture2D2);live2DModel.setTexture(2, texture2D2);

创建负责渲染Live2dCanvas的4乘4矩阵与赋值

 private Live2DModelUnity live2DModel;//制定显示位置与尺寸float modelWidth = live2DModel.getCanvasWidth();live2DCanvansPos = Matrix4x4.Ortho(0, modelWidth, modelWidth, 0, -50, 50);

给模型设置显示矩阵与更新和绘图的方法使用

在Update添加更新顶点的代码以及添加OnRenderObject的方法

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using live2d;public class Live2dModel : MonoBehaviour {public TextAsset modelFile;public Texture2D[] textures;private Live2DModelUnity live2DModel;private Matrix4x4 live2DCanvansPos;void Start () {//初始化Live2D.init();//释放//Live2D.dispose();//读取模型//Live2DModelUnity.loadModel(Application.dataPath + "/Resources/Epsilon/runtime/Epsilon.moc");//TextAsset mocFile = Resources.Load<TextAsset>("Epsilon/runtime/Epsilon.moc");live2DModel = Live2DModelUnity.loadModel(modelFile.bytes);//与贴图建立关联//Texture2D texture2D = Resources.Load<Texture2D>("");//live2DModel.setTexture(0,texture2D);//与多张贴图建立关联//Texture2D texture2D1 = Resources.Load<Texture2D>("Epsilon/runtime/Epsilon.1024/texture_00");//Texture2D texture2D2 = Resources.Load<Texture2D>("Epsilon/runtime/Epsilon.1024/texture_01");//Texture2D texture2D3 = Resources.Load<Texture2D>("Epsilon/runtime/Epsilon.1024/texture_02");//live2DModel.setTexture(0, texture2D1);//live2DModel.setTexture(1, texture2D2);//live2DModel.setTexture(2, texture2D2);for (int i = 0; i < textures.Length; i++){live2DModel.setTexture(i, textures[i]);}//制定显示位置与尺寸float modelWidth = live2DModel.getCanvasWidth();live2DCanvansPos = Matrix4x4.Ortho(0, modelWidth, modelWidth, 0, -50, 50);      }void Update (){live2DModel.setMatrix(transform.localToWorldMatrix * live2DCanvansPos);//更新顶点live2DModel.update();}private void OnRenderObject(){live2DModel.draw();}
}

运行程序,结果如下:

动作文件的加载与动作对象的实例化

两种实例化对象动作的方式,与模型的读取操作一样

        //实例化动作对象live2DMotionIdle = Live2DMotion.loadMotion(Application.dataPath + "");TextAsset mtnFile = Resources.Load<TextAsset>("");live2DMotionIdle = Live2DMotion.loadMotion(mtnFile.bytes);

动作属性的设置与动作管理的实例化

首先将动作属性进行导入

    public TextAsset[] motionFile;private Live2DMotion[] motions;motions = new Live2DMotion[motionFile.Length];for (int i = 0; i < motions.Length; i++){motions[i] = Live2DMotion.loadMotion(motionFile[i].bytes);}

对某一动作属性进行设置

        //设置某一个动画的一些属性//重复播放不淡入motions[0].setLoopFadeIn(false);//设置淡入淡出时间,参数单位为毫秒motions[0].setFadeOut(1000);motions[0].setFadeIn(1000);//动画是否循环播放motions[0].setLoop(true);

创建一个MotionQueueManager对motions进行管理

private MotionQueueManager motionQueueManager;motionQueueManager = new MotionQueueManager();motionQueueManager.startMotion(motions[0]);

动作的播放

按下M键可以改变人物的动作播放,将动作拖入Unity时也需要将动作的mtn文件修改为mtn.bytes。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using live2d;public class Live2dModel : MonoBehaviour {//模型public TextAsset modelFile;public Texture2D[] textures;private Live2DModelUnity live2DModel;private Matrix4x4 live2DCanvansPos;//动作public TextAsset[] motionFile;private Live2DMotion[] motions;private MotionQueueManager motionQueueManager;public int motionIndex;//private Live2DMotion live2DMotionIdle;void Start () {//初始化Live2D.init();//释放//Live2D.dispose();//读取模型//Live2DModelUnity.loadModel(Application.dataPath + "/Resources/Epsilon/runtime/Epsilon.moc");//TextAsset mocFile = Resources.Load<TextAsset>("Epsilon/runtime/Epsilon.moc");live2DModel = Live2DModelUnity.loadModel(modelFile.bytes);//与贴图建立关联//Texture2D texture2D = Resources.Load<Texture2D>("");//live2DModel.setTexture(0,texture2D);//与多张贴图建立关联//Texture2D texture2D1 = Resources.Load<Texture2D>("Epsilon/runtime/Epsilon.1024/texture_00");//Texture2D texture2D2 = Resources.Load<Texture2D>("Epsilon/runtime/Epsilon.1024/texture_01");//Texture2D texture2D3 = Resources.Load<Texture2D>("Epsilon/runtime/Epsilon.1024/texture_02");//live2DModel.setTexture(0, texture2D1);//live2DModel.setTexture(1, texture2D2);//live2DModel.setTexture(2, texture2D2);for (int i = 0; i < textures.Length; i++){live2DModel.setTexture(i, textures[i]);}//制定显示位置与尺寸float modelWidth = live2DModel.getCanvasWidth();live2DCanvansPos = Matrix4x4.Ortho(0, modelWidth, modelWidth, 0, -50, 50);//播放动作//实例化动作对象//live2DMotionIdle = Live2DMotion.loadMotion(Application.dataPath + "");//TextAsset mtnFile = Resources.Load<TextAsset>("");//live2DMotionIdle = Live2DMotion.loadMotion(mtnFile.bytes);motions = new Live2DMotion[motionFile.Length];for (int i = 0; i < motions.Length; i++){motions[i] = Live2DMotion.loadMotion(motionFile[i].bytes);}//设置某一个动画的一些属性//重复播放不淡入motions[0].setLoopFadeIn(false);//设置淡入淡出时间,参数单位为毫秒motions[0].setFadeOut(1000);motions[0].setFadeIn(1000);//动画是否循环播放motions[0].setLoop(true);motionQueueManager = new MotionQueueManager();motionQueueManager.startMotion(motions[0]);}void Update (){live2DModel.setMatrix(transform.localToWorldMatrix * live2DCanvansPos);if (Input.GetKeyDown(KeyCode.M)){motionIndex++;if (motionIndex >= motions.Length){motionIndex = 0;}motionQueueManager.startMotion(motions[motionIndex]);}//指定播放动作的模型motionQueueManager.updateParam(live2DModel);//更新顶点live2DModel.update();}private void OnRenderObject(){live2DModel.draw();}
}

多个动作的同时播放

多个动作同时播放只需要多创建一个MotionQueueManger来进行管理

private MotionQueueManager motionQueueManager;private MotionQueueManager motionQueueManagerA;motions[0].setLoop(true);motionQueueManager = new MotionQueueManager();motionQueueManager.startMotion(motions[0]);motions[5].setLoop(true);motionQueueManagerA = new MotionQueueManager();motionQueueManagerA.startMotion(motions[5]);motionQueueManager.updateParam(live2DModel);motionQueueManagerA.updateParam(live2DModel);

动作的优先级概念与设置标准

使用L2DMotionManager来对行为优先级进行管理

    private L2DMotionManager l2DMotionManager;//优先级的设置标准“//1.动作未进行的状态,优先级为0;//2.待机动作发生时,优先级为1;//3.其他动作进行时,优先级为2;//4.无视优先级,强制发生动作,优先级为3

动作优先级的代码实现

首先在Start里面进行L2DMotionManager的初始化

l2DMotionManager = new L2DMotionManager();

然后写一个通过优先级播放动作的方法StartMotion

    private void StartMotion(int motionIndex,int priority){if (l2DMotionManager.getCurrentPriority() >= priority){return;}else{l2DMotionManager.startMotion(motions[motionIndex]);}}

在Update里面进行使用调用

        //判断待机动作if (l2DMotionManager.isFinished()){StartMotion(0, 1);}else if (Input.GetKeyDown(KeyCode.M)){StartMotion(14, 2);}l2DMotionManager.updateParam(live2DModel);

开始时处于Idle状态,按下M后会变成摇头不高兴,播放完自己又会变成Idle

设置参数的方法

首先根据Epsilon.cmox文件把需要设置参数的id取出来,如图所示,取到角度X的id为PARAM_ANGLE_X

然后在Update里面添加下面的代码进行参数设置,第一个是id,第二个是需要设置的值,第三个是权重。

        //设置参数live2DModel.setParamFloat("PARAM_ANGLE_X", 30, 1);

参数的累加与扩大倍数的方法

        //设置参数live2DModel.setParamFloat("PARAM_ANGLE_X", 30, 1);//累加参数数值,一次增加10度live2DModel.addToParamFloat("PARAM_ANGLE_X", 10);//乘法设置参数live2DModel.multParamFloat("PARAM_ANGLE_X", 10);

通过索引获取参数并设置与参数的保存和回复

通过索引获取参数

        //第二种设置参数的办法,通过索引去设置int paramAngleX;paramAngleX = live2DModel.getParamIndex("PARAM_ANGLE_X");live2DModel.setParamFloat(paramAngleX, 30);

参数的保存和回复

        参数的保存与回复live2DModel.setParamFloat("PARAM_ANGLE_X", 30);保存与回复的参数是整个模型的所有参数,并不只是之前同方法里设置的几个参数live2DModel.saveParam();live2DModel.loadParam();

不透明度的设置与自动眨眼功能

不透明度的设置,需要设置的是模型的part部分

        //设定模型某一部分的透明度live2DModel.setPartsOpacity("PARTS_01_FACE_001", 0);

眨眼功能的实现,首先定义一个EyeBlinkMotion的类

private EyeBlinkMotion eyeBlinkMotion;

然后在Start方法里进行初始化

        //眨眼eyeBlinkMotion = new EyeBlinkMotion();

在Update方法里面进行调用

        //眨眼eyeBlinkMotion.setParam(live2DModel);

拖拽激发的动作

拖拽功能的实现,首先定义一个L2DTargetPoint的类

    //鼠标拖拽引起的动作变化private L2DTargetPoint drag;

然后在Start方法里进行初始化

        //鼠标拖拽drag = new L2DTargetPoint();

在Update方法里面进行调用

        //模型跟随鼠标转向与看向Vector3 pos = Input.mousePosition;if (Input.GetMouseButton(0)){//把屏幕坐标转换成live2D检测的坐标drag.Set(pos.x / Screen.width * 2 - 1, pos.y / Screen.height * 2 - 1);}

关于L2DTargetPoint获取坐标点的详细讲解

        //模型跟随鼠标转向与看向//得到的live2d鼠标检测点的比例值是-1到1(对应一个live2d拖拽//管理坐标系,或者叫做影响度)。//然后通过这个值去设置我们的参数,比如旋转30度*当前得到的值//就会按照这个值所带来的影响度去影响我们的模型动作//从而到达看向某一个点的位置

公式的验证与理解

实现模型跟随鼠标转向与看向的功能

在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();//模型的转向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());}

眼睛跟随鼠标移动

眼睛只望向前方

套用物理运算去设置头发的长度重量与收到的空气阻力

头发摇摆功能的实现,首先定义一个PhysicsHair的类

    //物理运算的设定(本模型头发只有两侧和后侧)private PhysicsHair physicsHairSide;private PhysicsHair physicsHairBack;

然后在Start方法里进行初始化和设置

        //头发的摇摆physicsHairSide = new PhysicsHair();physicsHairBack = new PhysicsHair();//套用物理运算//第一个参数是长度 单位是公尺 影响摇摆的快慢(周期)//第二个参数是空气阻力//第三参数是头发的重量physicsHairSide.setup(0.2f, 0.5f, 0.14f);

设置影响头发的输入参数

        //设置输入参数//社会哪一个部分变动时进行哪一种物理运算PhysicsHair.Src srcX = PhysicsHair.Src.SRC_TO_X;//横向摇摆//第三个参数,"PARAM_ANGLE_X"变动时头发受到0.005倍影响度的输入参数physicsHairSide.addSrcParam(srcX, "PARAM_ANGLE_X", 0.005f, 1);

设置头发的输出表现

因为该模型头发有两边,所以我们将之前设置的Hair都分成两个,为Left和Right。

        //设置输出表现PhysicsHair.Target targetLeft = PhysicsHair.Target.TARGET_FROM_ANGLE;//表现形式PhysicsHair.Target targetRight = PhysicsHair.Target.TARGET_FROM_ANGLE;physicsHairSideLeft.addTargetParam(targetLeft, "PARAM_HAIR_SIDE_L", 0.005f, 1);physicsHairSideRight.addTargetParam(targetRight, "PARAM_HAIR_SIDE_R", 0.005f, 1);

两边头发的横向摇摆效果

在Update里面进行调用

        //头发摇摆long time = UtSystem.getUserTimeMSec();//获取执行时间physicsHairSideLeft.update(live2DModel, time);physicsHairSideRight.update(live2DModel, time);

设置后边左边头发的摇摆效果

在Start里面添加下面的代码

        //左边的头发physicsHairBackLeft = new PhysicsHair();physicsHairBackLeft.setup(0.24f, 0.5f, 0.18f);PhysicsHair.Src srcXBackLeft = PhysicsHair.Src.SRC_TO_X;PhysicsHair.Src srcZBackLeft = PhysicsHair.Src.SRC_TO_G_ANGLE;physicsHairBackLeft.addSrcParam(srcXBackLeft, "PARAM_ANGLE_X", 0.005f, 1);physicsHairBackLeft.addSrcParam(srcZBackLeft, "PARAM_ANGLE_Z", 0.8f, 1);PhysicsHair.Target targetBackLeft = PhysicsHair.Target.TARGET_FROM_ANGLE;physicsHairBackLeft.addTargetParam(targetBackLeft, "PARAM_HAIR_BACK_L", 0.005f, 1);//右边的头发physicsHairBackRight = new PhysicsHair();physicsHairBackRight.setup(0.24f, 0.5f, 0.18f);PhysicsHair.Src srcXBackRight = PhysicsHair.Src.SRC_TO_X;PhysicsHair.Src srcZBackRight = PhysicsHair.Src.SRC_TO_G_ANGLE;physicsHairBackRight.addSrcParam(srcXBackRight, "PARAM_ANGLE_X", 0.005f, 1);physicsHairBackRight.addSrcParam(srcZBackRight, "PARAM_ANGLE_Z", 0.8f, 1);PhysicsHair.Target targetBackRight = PhysicsHair.Target.TARGET_FROM_ANGLE;physicsHairBackRight.addTargetParam(targetBackRight, "PARAM_HAIR_BACK_R", 0.005f, 1);

在Update里面添加下面的代码

        physicsHairBackLeft.update(live2DModel, time);physicsHairBackRight.update(live2DModel, time);

Live2d中的表情系统

首先定义三个变量

    //表情public TextAsset[] expressionFile;public L2DExpressionMotion[] expressions;private MotionQueueManager expressionMotionQueueManager;

在Start里面进行初始化

        //表情expressionMotionQueueManager = new MotionQueueManager();expressions = new L2DExpressionMotion[expressionFile.Length];for (int i = 0; i < expressions.Length; i++){expressions[i] = L2DExpressionMotion.loadJson(expressionFile[i].bytes);}

表情的播放

Update里面添加播放表情的代码,与播放动作的代码相似

        //播放表情if (Input.GetKeyDown(KeyCode.M)){motionIndex++;if (motionIndex >= expressions.Length){motionIndex = 0;}expressionMotionQueueManager.startMotion(expressions[motionIndex]);}

二次元日系游戏制作工具 - live2dSDK入门教程相关推荐

  1. 二次元日系游戏制作工具 - live2dSDK项目实战

    导入素材创建场景 游戏开始场景制作 星星闪耀动画的制作 特效孵化器 添加一个EffectSpawn脚本,用来泼撒花瓣和爱心 using System.Collections; using System ...

  2. Unity学习笔记—二次元日系游戏制作(实践篇-游戏初始化场景制作)

    原教程:siki:二次元日系游戏制作工具 - live2dSDK入门教程 http://www.sikiedu.com/my/course/282 (上)Unity学习笔记-二次元日系游戏制作(理论篇 ...

  3. Unity学习笔记—二次元日系游戏制作(理论篇)

    原教程:siki:二次元日系游戏制作工具 - live2dSDK入门教程 http://www.sikiedu.com/my/course/282 一.准备工作 1.下载安装:Live2D_Cubis ...

  4. Android 2D游戏引擎AndEngine快速入门教程

    Android 2D游戏引擎AndEngine快速入门教程 介绍:AndEngine是一款知名的Android 2D游戏引擎.该引擎代码开源,并且可以免费使用.本书详细讲解如何使用AndEngine引 ...

  5. ue4怎么用虚幻商城场景_【更新】UE4虚幻引擎野外场景制作零基础入门教程

    原标题:[更新]UE4虚幻引擎野外场景制作零基础入门教程 作为一套零基础入门教程,可以帮助虚幻4引擎的新手了解到环境制作流程和相关软件的配合.本教学适合零基础入门用户,不适合有一定经验的UE使用者. ...

  6. truffle (ETH以太坊智能合约集成开发工具) 入门教程

    truffle (ETH以太坊智能合约集成开发工具) 入门教程 前言 在你了解区块链开发之前,你有必要了解区块链的一些基础知识,什么是DApp,DApp与传统app的区别, 什么是以太坊,以太坊中的智 ...

  7. 认识AndEngine选自Android 2D游戏引擎AndEngine快速入门教程

    认识AndEngine什么是AndEngine 随着Android手机.平板的盛行,Android下的游戏也不断的变得火热.而对于游戏开发有兴趣的同学们,应该也想要学习开发游戏.虽说游戏开发的引擎较多 ...

  8. qpython3绘图_比Excel制图更强大,Python可视化工具Altair入门教程

    比 Excel 制图更强大,Python 可视化工具 Altair 入门教程 数据转化成更直观的图片,对于理解数据背后的真相很有帮助.如果你有这方面的需求,而且还在使用 Python,那么强烈推荐你试 ...

  9. 转载一个手机RPG游戏制作工具,仿造RPGXP写的

    转载一个手机RPG游戏制作工具,仿造RPGXP写的 有朋友问有没有脚本编辑功能,大家注意啦: 有脚本编辑功能,可视化界面编辑脚本,和RMXP一样 经过一年的开发,手机RPG游戏制作工具--MobieG ...

  10. 大白菜U盘启动盘制作工具完整使用教程

    目录 一.制作前的准备工作 二.制作U盘启动盘 三.将U盘设置为优先启动项 四.U盘重装系统 大白菜U盘启动盘制作工具完整使用教程 大白菜是一款具有支持提取安装文件,并自动进行系统安装和引导修复过程等 ...

最新文章

  1. AlexeyAB DarkNet YOLOv3框架解析与应用实践(一)
  2. Codeforces Round 542 (Div. 2)
  3. python 中set集合类型(去重、成员运算)
  4. 关于 early Z 与 z-prepass
  5. hdu 5434(状态压缩+矩阵优化)
  6. 小游戏发布云测试工具,中小团队的“小又快”可以这么来
  7. Page.ClientScript.RegisterStartupScript() 方法与Page.ClientScript.RegisterClientScriptBlock() 方法
  8. UVA10193 All You Need Is Love【进制+GCD】
  9. 华硕固件默认ip_斐讯刷华硕固件后开启QOS限速的方法
  10. 软件设计师2021考试大纲
  11. cesium使用obj格式的3D模型
  12. js判断数组是否为空
  13. 小明发布_每日LOL圈:LPL春季赛将于13号开赛;小明、阿水、Meiko多人聚餐
  14. #762 (Div. 3) E. MEX and Increments(贪心构造
  15. RSA、SM2公钥证书信息的读取
  16. 李建忠设计模式之“对象创建”模式
  17. linux qq无法登录服务器,如何在Linux系统中使用QQ
  18. 【Aegisub相关】VSCode插件:Aegisub Helper的安装、功能介绍及使用方法
  19. Tableau同环比分析系列(一)--基础同比、环比
  20. 力引导算法深入理解及其在d3.js中实现的源码分析

热门文章

  1. Origin 去demo水印
  2. 编程小白C语言例题4
  3. TextMesh Pro不能显示中文的解决办法是创建字贴图,常用汉字3500
  4. navicat11全系列破解教程
  5. 小程序影藏溢出的gif_动图制作方法,1分钟教会你如何制作gif表情包!
  6. 计算机组成之总线结构
  7. java实现七种经典排序算法
  8. 介绍几个json在线格式化网站
  9. Linux中安装JDK
  10. cms完整视频教程+源码 孔浩老师 全131讲