在博客养一只猫 -- Live2D SDK 4.x 探索
提前声明,这不能当教程,只是一份笔记,还有吐槽。
搞一只看版猫到博客居然比搞一只看板娘还要麻烦……囧
虽说最后猫是放出来了,但八成还是哪里没用对吧,编译出来动辄四五百kb的js文件(虽然确实是没有特别狠的压缩,uglify全开之后运行会出错……),还有官方原版Demo直接编译出的1.6MB js+sourcemap(不含模型与图片),怎么看怎么别扭(捂脸)…… 这个只有短短5页的官方文档也是没说多少东西,也可能是因为大部分用户都是开发手机原生应用,而不是网页的吧。
要找教程的话,往这边走吧~
其他人努力研究的v4 SDK教程:
- https://blog.csdn.net/qq_37735413/article/details/119413744 (让我意识到了模型使用非标准参数名的问题)
还不清楚是哪个版本,但是文档链接很多:
应该是旧版本SDK的应用:
- https://blog.csdn.net/qq_37735413/article/details/104769280
- https://github.com/EYHN/hexo-helper-live2d
Live2D
就是目前的很多手机游戏里2D 动态立绘背后的那个技术,或者说,一套专门应对活动幅度较小的类生物的2D 动画生成技术。我的直观印象是一套可以灵活控制的形变系统 + 物理 + 模型和动作管理。
Live2D 官网大多的模型样例(除了有三方版权的)大多是对一般使用者和小型公司免费的。这只猫就是tororo&hijiki包里的其中一只。
使用
使用Live2D需要有:
- 模型: 包括texture、部件、参数(上面绑有不同部件的关键帧)、动作(部件、组件参数变化)
- SDK
模型
Runtime里的model3.json长这个样子:
其中.2048文件夹里是材质png图片,
motion文件夹是每个动作的json(每个动作,各部件网格顶点位置变化等),
cdi3是参数的描述的样子(但也并不是到default parameter的mapper...),
moc3是模型文件,里面包含部件和参数的设定,
model3是对模型的描述和配置,
physics3是一些物理(如头发摆动?)和动画的参数,
pose3似乎是同一部位的多个图片(如无法靠单一图片形变做到的,同一部件的不同状态)
杂谈
说到动画,就想跟死掉的Flash比较一下。小学的时候,Flash在我心目中的一大黑科技就是补间动画。给出形状A和形状B,计算从A变成B之间的过程并自动填补关键帧。但除非图形规则,这个生成的补间对用户来说基本是不可控的。中间过程可能生成得很自然,也可能先从A扭曲成奇怪的图案,再变成正常的B。当然,这种情况,大家一般会删了补间,在中间加几个缓冲的关键帧(我们预期的中间状态),让帧与帧之间的差异更小,变化更规则,再创建补间。Live2D 这边,通过在图形上创建由多个三角形组成的多边形网格(一堆三角形可以组合出各种多边形),拖拽网格上节点造成形变生成关键帧。然后因为这些形变都被这些节点的移动描述了,补间的生成就会很规则。
印象中与Flash几乎同期的,还有一个基于骨骼生成补间的Moho。查了下它还好好活着……是在图片上创建并绑定骨架,通过拖拽骨架顶点对图片进行形变来创建关键帧,然后创建补间。感觉很像是Flash和Live2D的中间状态。
Live2D SDK for Web
模型自定义参数名的问题
比较快速但一点也不正规的操作:改Framework/src/cubismdefaultparameterid.ts
附camel case与snake case可以放进浏览器console转换:
/*
目标参数名 json示例 (猫的模型tororo和hijiki使用的参数命名)
{
"ParamAngleX": "PARAM_ANGLE_X",
"ParamAngleY": "PARAM_ANGLE_Y",
"ParamAngleZ": "PARAM_ANGLE_Z",
}
默认参数名json示例
{
"ParamAngleX": "ParamAngleX",
"ParamAngleY": "ParamAngleY",
"ParamAngleZ": "ParamAngleZ",
}
*/
//主要是需要这个,因为默认是camel case,但有些模型是snake case
function camel_to_snake(name) {
return name.replace(/([A-Z])/g,"_$1").toLowerCase().substring(1);
}
for(k in json){
json[k] = camel_to_snake(json[k]).toUpperCase();
}
function snake_to_camel(name) {
return name.split("_")
.map(x => x.slice(0,1).toUpperCase()+
x.slice(1).toLowerCase()).join('');
}
当然了,如果压根就不在所谓“标准参数”列表里,那也就没什么简便办法了。
事件监听与动作的问题
总之,在官方Github的例子里,事件监听在lappdelegate.ts,如下部分。自行按需改动,比如把canvas.ontouchmove改成document.ontouchmove之类的。
if (supportTouch) {
// タッチ関連コールバック関数登録
canvas.ontouchstart = onTouchBegan;
canvas.ontouchmove = onTouchMoved;
canvas.ontouchend = onTouchEnded;
canvas.ontouchcancel = onTouchCancel;
} else {
...
}
动作在lapplive2dmanager.ts里(这个onTap这里):
public onTap(x: number, y: number): void {
if (LAppDefine.DebugLogEnable) {
LAppPal.printMessage(
`[APP]tap point: {x: ${x.toFixed(2)} y: ${y.toFixed(2)}}`
);
}
for (let i = 0; i < this._models.getSize(); i++) {
if (this._models.at(i).hitTest(LAppDefine.HitAreaNameHead, x, y)) {
if (LAppDefine.DebugLogEnable) {
LAppPal.printMessage(
`[APP]hit area: [${LAppDefine.HitAreaNameHead}]`
);
}
this._models.at(i).setRandomExpression();
} else if (this._models.at(i).hitTest(LAppDefine.HitAreaNameBody, x, y)) {
if (LAppDefine.DebugLogEnable) {
LAppPal.printMessage(
`[APP]hit area: [${LAppDefine.HitAreaNameBody}]`
);
}
this._models
.at(i)
.startRandomMotion(
LAppDefine.MotionGroupTapBody,
LAppDefine.PriorityNormal,
this._finishedMotion
);
} else {
if (LAppDefine.DebugLogEnable) {
LAppPal.printMessage(
`[APP]hit area: None`
);
}
this._models
.at(i)
.startRandomMotion(
LAppDefine.MotionGroupTap,
LAppDefine.PriorityNormal,
this._finishedMotion
);
}
}
}
也可以在监听器里直接这样触发动作的更新
let instance = LAppLive2DManager.getInstance();
instance._models.at(0).startRandomMotion(
LAppDefine.MotionGroupTap,
//其实就是model3里的动作, 比如"Tap", "Flick"
LAppDefine.PriorityNormal,
//更换动作的优先级
instance._finishedMotion
//回调,其实就在console打印了个 Motion Finished
);
应用于Ghost CMS的问题
由于目前Ghost CMS不支持图片、js、css以外的静态资源,模型是不可以直接打包在Theme里的,不然读取json和moc文件会直接301然后404。
解决方案
需求:让脚本能够成功的加载模型(静态资源,.json, .moc, .png等等),最好还不要跨域。
情况:Ghost官方估计不会这么做的,它们都声明过连媒体库都不做。
暴力的办法:反正本来网站也是nginx反代的,在相同域名下直接多配置一个location在根之前进行匹配,用于加载模型。
location /live2d/ {
root /somepath/somepath;
autoindex on;
}
如上,把模型放在/somepath/somepath/live2d目录下,然后在themes的js里从/live2d/加载模型就行了。