Live2D

参考链接:SIKI学院

一、前言:

1/ 官网:www.live2d.com

2/ 下载

需求下载1:Cubism SDK for Unity下载地址:https://www.live2d.com/download/cubism-sdk/

需求下载2:Cubism下载地址:https://www.live2d.com/download/cubism/

Live2D Cubism:美术用的2D建模软件,下载好后安装,打开可以免费使用一段时间的专业版。

需求下载3:模型数据下载:https://www.live2d.com/download/sample-data/

3/ 静态变动态原理

在图上添加一些点,通过这些点来扭曲图片,通过障眼法表现出动来动去的感觉。相当于在操作一些图层。

4/ 软件版本

2.x用的较多,3.x最新版。本例使用2.x版本。

二、操作

解压下载好的sdk2.x Live2D_SDK_Unity_2.1.04_2_jp,得到如下目录:

  • framework框架代码
  • lib用到的库
  • sample文件夹下为案例功能,可以分别打开看下玩下
  • tool工具
  • ReadMe.txt

1.体验

分别打开上sample文件夹下工程,体验下。

2.尝试

1/ 导入模型数据:

把上面下载好的**[需求下载3]模版数据(如“miku_sample.cmox”)拖入Cubism Editor[需求下载2]**中,这个文件Unity无法使用,需要使用Cubism导出moc文件。

加载好后,可以看到:

2/ 导出moc:

菜单File-Export For Runtime-Export as moc file(for 2.1)根据自己的sdk版本选择导出2.x或者3.x。

注:若菜单是暗的不能点,则说明是免费版,没有这个功能。

弹出菜单使用默认选项,然后导出一个moc文件,正是我们所需要的,放在原来的模型文件夹下,和.cmox文件同级。

3/ Unity中查看下载的模型的效果

  • 打开上sample文件夹下simple工程,打开Sample场景;

  • 把整个模型文件夹拖入unity项目,然后复制一份模型文件夹下最外层的.moc文件,并修改.moc为.bytes;

  • 然后修改Sample场景下的Live2DModel物体上SimpleModel组件的值,mocFile拖入刚刚新的moc的bytes文件,TextureFiles拖入模型的贴图。

  • 运行游戏,发现新的模型已经正确显示在场景中了。

3.使用

此处引用老师给的笔记:

Live2D模型制作到显示的基本流程:1.初始化模型。       1.制作模型(读取moc文件)。      2.与贴图建立关联。      3.与绘图环境建立链接。(有些平台不需要)。   4.制定显示位置与尺寸。2.更新模型状态。    1.更新顶点。  2.绘图。

1/ 创建新的工程,(本人版本Unity2017.4.29),拖入上sdk解压得到的这几个文件夹:
framework、lib、tool;

2/ 在[模型下载3]的链接里下载你想要的模型,此处使用"Epsilon",拖到项目里的Resources文件夹下,并新增Live2dModel.cs添加下列代码。

3/ 使用Live2D前需要初始化:

using live2d;
//初始化
Live2D.init();

4/ 读取模型的两种方式:

//方式1:直接使用runtime文件夹下moc文件
Live2DModelUnity.loadModel(Application.dataPath+ "/Resources/Epsilon/runtime/Epsilon.moc");//方式2:加载二进制文件并读取:
//先复制上moc文件,并添加后缀.bytes,文件可放在Resources文件夹下然后加载:
TextAsset mocFile = Resources.Load<TextAsset>("Epsilon/runtime/Epsilon.moc");
Live2DModelUnity live2DModel=Live2DModelUnity.loadModel(mocFile.bytes);
//也可以直接public TextAsset mocFile这样开放出来,然后直接拖入bytes文件到组件上。

5/ 与贴图建立关联(假设已经使用上条的方式2获得了live2DModel变量)

//方式1:根据路径
//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, texture2D3);//方式2:拖入组件public Texture2D[] textures;
for (int i = 0; i < textures.Length; i++)
{live2DModel.setTexture(i, textures[i]);
}

6/ 指定显示位置与尺寸(使用正交矩阵与相关API显示图像,再由游戏物体的位置和摄像机的size调整图像到合适的位置

  private Matrix4x4 live2DCanvasPos;//live2d自身的画布float modelWidth = live2DModel.getCanvasWidth();//创建正交投影矩阵,参数为正交视口的左,右,下,上,近视口距离,远视口距离live2DCanvasPos = Matrix4x4.Ortho(0, modelWidth, modelWidth, 0, -50, 50);

7/ 更新模型状态:更新顶点

void Update () {live2DModel.setMatrix(transform.localToWorldMatrix * live2DCanvasPos);live2DModel.update();
}

8/ 更新模型状态:绘图

private void OnRenderObject()
{live2DModel.draw();
}

然后这个脚本挂在场景中的一个物体上,运行游戏,可以看到小姐姐的静态模型了。可以调整摄像机参数控制看到的小姐姐的大小。

下面看动作播放:

动作文件为runtime/motions文件夹下的mtn文件。

9/ 播放动作:加载动作文件

//方式1:直接加载mtn文件:
//Live2DMotion.loadMotion(Application.dataPath+"路径");//方式2:加载bytes文件,加载或者直接拖进组件(同样,把mtn文件复制一份加.bytes后缀)
//Live2DMotion.loadMotion(mtnFile.bytes);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);
}

10/ 设置某一个动画的一些属性

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

11/ 播放动作

//进行完上述操作后,播放动作:
//动作管理
private MotionQueueManager motionQueueManager;
motionQueueManager = new MotionQueueManager();
motionQueueManager.startMotion(motions[0]);在Update中播放动作:
void Update () {live2DModel.setMatrix(transform.localToWorldMatrix * live2DCanvasPos);//使这个模型播放动作motionQueueManager.updateParam(live2DModel);live2DModel.update();
}动作的bytes拖进去后,发现可以播放了。

12/ 同时播放多个动作(如脸部和身体动作拆开了,需要自由组合播放)

//有几个动作同时播放,就需要几个MotionQueueManager
//在上面的步骤11基础上,再同时播放动作5:播放多个动作
//motions[5].setLoop(true);
//private MotionQueueManager motionQueueManagerA;//在函数外部加上这个motionQueueManagerA = new MotionQueueManager();
motionQueueManagerA.startMotion(motions[5]);void Update () {live2DModel.setMatrix(transform.localToWorldMatrix * live2DCanvasPos);motionQueueManager.updateParam(live2DModel);motionQueueManagerA.updateParam(live2DModel);//加上这句live2DModel.update();
}

注意:如果需要多个动作同时播放,尽可能不要设置相同的参数。

13/ 动作的优先级

 //优先级
//L2DMotionManager继承自MotionQueueManager
//优先级的设置标准:
//1.动作未进行的状态,优先级为0。
//2.待机动作发生时,优先级为1。
//3.其他动作进行时,优先级为2。
//4.无视优先级,强制发生的动作,优先级为3。 //上述代码为测试直接播放某个动作,下面开始把动作串起来
//初始默认播放待机动作,然后有事件过来播放其他动作时,根据优先级播放其他动作,结束了返回默认动作private L2DMotionManager l2DMotionManager;//目前使用的动作管理器//初始化  动作的优先级使用:
l2DMotionManager = new L2DMotionManager();//根据动作优先级播放动作接口:
private void StartMotion(int motionIndex,int priority)
{if (l2DMotionManager.getCurrentPriority()>= priority){return; }l2DMotionManager.startMotion(motions[motionIndex]);
}//然后在Update中判断是否有正在播放的动画,没有则播放待机
void Update () {live2DModel.setMatrix(transform.localToWorldMatrix*live2DCanvasPos);判断待机动作if (l2DMotionManager.isFinished()){StartMotion(0,1);}else if (Input.GetKeyDown(KeyCode.M))//测试高优先级打断{StartMotion(14,2);}l2DMotionManager.updateParam(live2DModel);
}

14/ 设置参数

//如图所示 中间栏下方可以通过拖动来改变参数从而改变模型的显示效果,在Unity里也可以通过代码控制//设置参数,paramID获得方式见下图(2.x版本需要模型源文件,不然不知道参数id,需要建模师给到配置表;3.x版本可以直接设置)
//在Update中设置。
//方式1:live2DModel.setParamFloat(string paramID, float value, float weight = 1影响度);//设置为指定值//如: live2DModel.setParamFloat("PARAM_ANGLE_X",1);//方式2:live2DModel.addToParamFloat(string paramID, float value);//当前值累加//方式3:live2DModel.multParamFloat(string paramID, float value);//当前值扩大倍数//上几个函数都有重载,参数id可以传入索引int值,其中这个索引可以通过这个函数获取
int paramAngleX = live2DModel.getParamIndex("PARAM_ANGLE_X");
live2DModel.setParamFloat(paramAngleX,30);//参数的保存与恢复
//保存与恢复的参数是整个模型的所有参数,并不只是之前同方法里设置的某几个参数
//live2DModel.saveParam();
//live2DModel.loadParam();

15/ 设置模型某一部分的不透明度

//live2DModel.setPartsOpacity(string partId, 0);
//partId获得方式见下图,要使用整个文件夹的id,不要选择文件夹里小部件。

16/ 自动眨眼

 private EyeBlinkMotion eyeBlinkMotion;
//初始化eyeBlinkMotion = new EyeBlinkMotion();
在Update中调用:eyeBlinkMotion.setParam(live2DModel);

17/ 模型跟随鼠标转向与看向

private L2DTargetPoint drag;
//初始化
drag = new L2DTargetPoint();//在Update中://得到的Live2d鼠标检测点的比例值是-1到1(对应一个live2d拖拽
//管理坐标系,或者叫做影响度。)
//然后我们通过这个值去设置我们的参数,比如旋转30度*当前得到的值
//就会按照这个值所带来的影响度去影响我们的模型动作
//从而到达看向某一个点的位置
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)
{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());
}

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

 //物理运算的设定
private PhysicsHair physicsHairSideLeft;
private PhysicsHair physicsHairSideRight;
private PhysicsHair physicsHairBackLeft;
private PhysicsHair physicsHairBackRight;#region 左右两侧头发的摇摆
//左测旁边的头发
physicsHairSideLeft = new PhysicsHair();
//套用物理运算
physicsHairSideLeft.setup(0.2f, // 长度 : 单位是公尺 影响摇摆周期(快慢)0.5f, // 空气阻力 : 可设定0~1的值、预设值是0.5 影响摇摆衰減的速度0.14f); // 质量 : 单位是kg 
//设置输入参数
//设置哪一个部分变动时进行哪一种物理运算
PhysicsHair.Src srcXLeft = PhysicsHair.Src.SRC_TO_X;//横向摇摆//第三个参数,"PARAM_ANGLE_X"变动时头发受到0.005倍的影响度的输入参数
physicsHairSideLeft.addSrcParam(srcXLeft, "PARAM_ANGLE_X",0.005f,1);//设置输出表现
PhysicsHair.Target target = PhysicsHair.Target.TARGET_FROM_ANGLE;//表现形式physicsHairSideLeft.addTargetParam(target, "PARAM_HAIR_SIDE_L",0.005f,1);//右侧旁边的头发
physicsHairSideRight = new PhysicsHair();
//套用物理运算
physicsHairSideRight.setup(0.2f, // 长度 : 单位是公尺 影响摇摆周期(快慢)0.5f, // 空气阻力 : 可设定0~1的值、预设值是0.5 影响摇摆衰減的速度0.14f); // 质量 : 单位是kg 
//设置输入参数
//设置哪一个部分变动时进行哪一种物理运算
PhysicsHair.Src srcXRight = PhysicsHair.Src.SRC_TO_X;//横向摇摆
//PhysicsHair.Src srcXRight = PhysicsHair.Src.SRC_TO_Y;//第三个参数,"PARAM_ANGLE_X"变动时头发受到0.005倍的影响度的输入参数
physicsHairSideRight.addSrcParam(srcXRight, "PARAM_ANGLE_X", 0.005f, 1);//设置输出表现
PhysicsHair.Target targetRight = PhysicsHair.Target.TARGET_FROM_ANGLE;//表现形式physicsHairSideRight.addTargetParam(targetRight, "PARAM_HAIR_SIDE_R",0.005f,1);#endregion#region 左右后边头发的摇摆
//左边
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);#endregion//在Update中:
long time = UtSystem.getUserTimeMSec();//执行时间
physicsHairSideLeft.update(live2DModel,time);
physicsHairSideRight.update(live2DModel,time);
physicsHairBackLeft.update(live2DModel, time);
physicsHairBackRight.update(live2DModel,time);

19/ 表情系统(特殊的动作)

public TextAsset[] expressionFiles;
public L2DExpressionMotion[] expressions;
private MotionQueueManager expresionMotionQueueManager;
public int motionIndex;//初始化
expresionMotionQueueManager = new MotionQueueManager();
expressions = new L2DExpressionMotion[expressionFiles.Length];
for (int i = 0; i < expressions.Length; i++)
{expressions[i] = L2DExpressionMotion.loadJson(expressionFiles[i].bytes);
}在Update中加入测试表情:
if (Input.GetKeyDown(KeyCode.M))
{motionIndex++;if (motionIndex >= expressions.Length){motionIndex = 0;}expresionMotionQueueManager.startMotion(expressions[motionIndex]);
}
expresionMotionQueueManager.updateParam(live2DModel);//可以看到使用方式和普通动作是一样的,只是
//Live2DMotion  <->  L2DExpressionMotion,都继承自AMotion

4.官方demo中的框架

官方sdk2.x中的demo:SampleApp1中使用的框架,可以按照这个来;这里提取出需要的,打一个package,内容如下:

链接:https://pan.baidu.com/s/13MLVGX-CwmTjN9ENJ600ew

在导入sdk2.x的基础上,再导入这个包。

使用:(此处使用haru模型资源,见共享链接里)

新建个空物体,挂上MeshFilter组件,拖入Live2D_Canvas资源;
挂上LAppModelProxy组件,Path填写模型json文件在Resources下相对地址,包含后缀名;
挂上MyGameController组件,运行。

可根据需求修改。(如关闭运行时日志LAppDefine.DEBUG_LOG)

 /**开始运动。*检查您是否可以播放,如果不能这样做,则无所事事。*如果您可以自动播放,请阅读文件并进行播放。*如果它有声音,它也会播放。*如果您有关于淡入和淡出的信息,请在此处设置。 如果没有初始值。*group:动作名称,如下图红框,见模型的json文件*no:索引,0开始*/
lAppModelProxy.GetModel().StartMotion(string group, int no, int priority);
如:lAppModelProxy.GetModel().StartMotion("tap_body",0,2);

//播放表情
//name为上图json中的"expressions"里的name,如“f01”
lAppModelProxy.GetModel().SetExpression(string name)//显隐
lAppModelProxy.SetVisible(true);//换装(需要多张图的衣服部件的布局一致)Live2DModelUnity live2DModelUnity = lAppModelProxy.GetModel().GetLive2DModelUnity();live2DModelUnity.setTexture(int textureNo, Texture2D texture);

5.3.x版本的更新

1/ 动作参数和部位的不透明度参数都可视化了,可以直接在unity面板上调整。

2/ Cubism导出3.x的模型数据时,放到unity里面可以看到直接是一个可识别的预制文件,可以直接拖到场景使用。

3/ 动画制作,直接用Animation。

6.网上的破解资源的处理

文件用记事本打开,可以打开的话,根据内容修改文件名和后缀,后缀一般.txt
图和moc文件一般都是png和moc,不用修改后缀。

若文本内容为:{“type”:“Live2D Expression”,表示这是个表情;
若文本内容为:# Live2D Animator Motion Data,表示这是个动作文件;
若文本内容为:{“version”:"…",“model”:…,“textures”:…,表示这是个模型json文件,根据里面内容,修改外面各文件的名称和相对路径。

然后这个文件夹可以放在项目里测试使用了。


所需要的资源及2.x版本sdk:
链接:SIKI学院
https://pan.baidu.com/s/1KHeuxvdZyYjQPocaveYjbw 提取码:d5qn

[Unity插件]Live2D插件学习相关推荐

  1. 在Unity中Live2D插件实现动态桌面

    之前解了三国杀的包,拿三国杀的皮肤做了几个动态壁纸,已经拿到好几千的订阅了,这次突发奇想把碧蓝航线的Live2D皮肤拿来做动态桌面,顺便做个互动. 先放初步构图: 目前互动上还有些小bug和语音还需要 ...

  2. Unity插件之NGUI学习(4)—— 创建UI2DSprite动画

    创建一个新的Scene.并按 Unity插件之NGUI学习(2)创建UI Root,并在UI Root的Camera下创建一个Panel. 然后在选中Panel,在菜单中选择NGUI->Crea ...

  3. Unity插件之NGUI学习(8)—— Table和NGUI尺寸转换为世界坐标系尺寸

    依据 Unity插件之NGUI学习(2),创建一个UI Root,在UI Root下创建一个Texture作为背景图,并设置图片,在Wiget下调整大小:然后在UI Root下再创建一个Panel. ...

  4. Unity的NGUI插件篇——入场效果

    Unity的NGUI插件篇--入场效果 入场效果 入场效果需要借助于NGUI提供的TweenPosition类来完成,为了说明此类的使用方法,本节将使会讲解两个示例.本文选自  大学霸 <NGU ...

  5. .net 插件式开发学习总结

    .NET简谈插件系统开发模式 今天跟大家分享一下我们在日常开发中并不常用的开发模式"插件系统模式",什么叫插件从大一点的概念讲就是我们开发的软件是由很小的模块组成,每一块都能成功的 ...

  6. Unity时钟定时器插件

    Unity时钟定时器插件 http://dsqiu.iteye.com/blog/2020603 https://github.com/joserocha3/KillerCircles/blob/67 ...

  7. 基于jquery的插件turn.js学习笔记

    基于jquery的插件turn.js学习笔记 简介 turn.js是一个可以实现3d书籍展示效果的jq插件,使用html5和css3来执行效果.可以很好的适应于ios和安卓等触摸设备. How it ...

  8. Unity好用插件集合1

    插件集合 3D Character Pack 4 characters LuciSoft 3D Low Poly Car For Games 14 Arrow Animations 1.0 A Pat ...

  9. Unity 大气特效插件分析 - Aura #01

    老实说我也不知道该叫啥了这标题wwww Aura是一个Unity的开源插件,可以实现较为出色的大气效果(如:体积光,体积雾等等): 传送门: Asset store: https://assetsto ...

  10. 浏览器插件的开发学习

    今天闲来无事,想到公司在开发浏览器插件的问题上比较纠结,所以我整理了下,以便以后用到可以快速上手 谷歌浏览器插件是一种小型的用于定制浏览器体验的程序.通过插件,可以自定义浏览器的一些行为来适应个人的需 ...

最新文章

  1. 【响应式Web前端设计】CSS 定位详解
  2. phpStorm 2016.1 最新版激活方法
  3. 【青铜打铁篇】Activiti 工作流从入门到入土?
  4. WPS Office文档未保存怎么恢复
  5. java 单链表是否有环,判断链表中是否有环
  6. 在 vb.NET 中使用 COM+ 服务
  7. 一步一步理解拖拽Drag(四)
  8. IBM斥资20亿美元的收购,天气数据为何值钱?
  9. VMware克隆CentOS6.4后 eth0无法初始化
  10. 东南大学c++非电类期末试卷 程序设计与算法语言,挑战程序设计竞赛2:算法和数据结构 中文完整pdf版[55MB] 附源码...
  11. Html学习手册(W3CSchool.chm)
  12. 助你成为Java大神的十个建议
  13. 【RocketMQ】Send [1] times, still failed以及No route info of this topic问题排查思路总结
  14. 从函数式编程到Promise
  15. web前端 vue axios 网页设计
  16. 网站添加百度分享工具的好处
  17. Gunicorn系列之利用Gunicorn启动项目
  18. 关于Windows Paint的基础图层透明背景的操作说明
  19. java树结构模糊查询
  20. MarkDown 图片和链接

热门文章

  1. VS2010安装部署成.NET 2.0过程的几个问题
  2. Dell也来凑热闹,传将数月内发售Android手机Mini 3i
  3. 湖南省对口升学c语言试题,湖南省对口升学计算机专业综合试卷试题.doc
  4. linux恢复表数据,Linux恢复误删的数据
  5. python多元线性回归_多元线性回归模型精度提升 虚拟变量
  6. Qt使用paintevent事件绘制图像(可进行缩放且能够局部放大)
  7. power designer 连接数据库以及 Could not Initialize JavaVM! 错误的解决
  8. WIN32 汇编 工具栏的使用
  9. 用Matlab求解高等数学中的问题(求极限,求导)
  10. c语言学习系统(学习c语言用什么软件)