日记--无法成功的看板娘

突发奇想要给博客装一个live2D的看板娘,尝试了一下基本确认是模型本身太复杂导致目前所有的live2D插件都无法兼容,目前兼容最好的是oh-my-live2d,但也依然无法正常显示模型。决定留给日后学习自己制作live2D模型时再做简化。

1. Vtuber Studio 中使用的模型文件

Vtuber Studio(以及大多数Vtuber软件如VUP、PrprLive等)使用的Live2D模型通常是一个打包好的成品文件,目的是为了方便导入和运行。

  • 核心文件
    • *.cmo3 文件:这是最常见的格式。它是由Live2D Cubism Editor导出的一种整合包,里面已经包含了模型数据(moc3)、纹理(图片)、物理、动作(motion)、表情(expression)等所有必要文件。用户只需要这一个文件即可导入软件。
    • [模型名称].model3.json:有时软件也会要求这种格式。它本质上是一个模型配置清单文件(JSON格式),但它需要与一个包含所有资源(moc3文件、纹理集、动作等)的文件夹配套使用。
  • 支持文件
    • 纹理图片(通常是.png格式)
    • 动作文件(.motion3.json
    • 表情文件(.exp3.json
    • 物理文件(.physics3.json
    • 等等。但这些文件通常都被打包在.cmo3里了,用户看不见。

特点封闭、整合。为了方便普通用户,所有东西都打包在一起,只需一键导入。


2. 个人博客看板娘使用的文件

网页端的Live2D看板娘(例如使用hexo-helper-live2dLive2D Widget等插件)需要被浏览器加载和渲染,因此文件必须是离散的、可被网络请求的

  • 核心文件
    • [模型名称].model3.json这是必须的! 它是模型的“说明书”,告诉JavaScript库如何组装这个模型,比如moc文件在哪、贴图用哪张、动作和表情文件有哪些。
    • *.moc3 文件:这是模型的核心骨骼和变形数据,由Cubism Editor导出,是二进制文件。
    • 纹理图片:通常是.png格式的图片,可能有多张(如texture_00.png, texture_01.png)。
    • 动作文件.motion3.json 文件,定义了模型的一系列动作。
    • 表情文件.exp3.json 文件,定义了模型的各种表情。
    • 物理文件.physics3.json 文件,定义了头发、衣物等部位的物理模拟规则。
    • 其他:可能还包括pose.json(初始姿势)和userdata.json等。

特点开放、离散。每个文件都是独立的,需要被网页逐个请求加载。


3. 两者有很大的区别吗?

有很大的区别,但核心模型数据是相通的。

特性 Vtuber Studio 模型 网页看板娘模型
格式 主要是单一的 .cmo3 整合包 离散的多个文件(.model3.json, .moc3, .png 等)
目的 为桌面软件优化,一键导入 为网络加载优化,可分块请求
使用方式 封闭,用户不直接操作内部文件 开放,需要明确指定每个文件的路径
核心数据 内部包含 .moc3 和纹理 外部需要 .moc3 和纹理文件

简单比喻

  • Vtuber Studio的.cmo3 像一个压缩好的.zip安装包,双击就能安装。
  • 网页看板娘 像是一个文件夹里的源代码资源文件,需要被程序读取并组装。

它们的底层都是Live2D Cubism引擎,所以模型本身(moc3数据)是通用的,只是打包和分发的方式不同


4. 如何将Vtuber Studio的模型变为博客看板娘?

这是最关键的一步。因为你手里只有.cmo3文件,而网页需要离散的文件。你有以下几个选择,按推荐度排序:

如果有原始模型文件(最佳方案)

这是最直接、最完美的方法。.cmo3文件是无法反向解包出原始离散文件的。

  • 联系模型师:直接联系为你制作模型的画师或模型师,向他说明你需要将模型用于网页端,请他提供“用于Web发布的模型文件包”
  • 他会提供什么:一个包含model3.json.moc3、所有.png贴图、以及motions(动作)文件夹的完整资源包。你只需要把这个文件夹放到你的博客目录下,并在看板娘插件中配置model.json的路径即可。

文件夹结构通常如下:

1
2
3
4
5
6
7
8
9
your_model/
├── your_model.model3.json <-- 这是核心配置文件
├── your_model.moc3
├── texture_00.png
├── texture_01.png
└── motions/
├── idle.motion3.json
├── tap_body.motion3.json
└── ...
  1. 将整个 your_model 文件夹上传到你的博客服务器或博客相关的目录下(例如 /live2d_models/your_model/)。

  2. 根据你使用的看板娘插件(如 hexo-helper-live2d),在博客的配置文件中指定模型路径:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    live2d:
    enable: true
    scriptFrom: local
    model:
    use: your_model # 模型文件夹名称
    scale: 0.8
    display:
    position: right
    width: 150
    height: 300
    mobile:
    show: true

    插件会自动去找到 /live2d_models/your_model/your_model.model3.json 文件并加载。

文件结构

这里以TN_2025Q_V1.0.0模型举例,模型作者:TN酱

核心必需文件(有了这些,看板娘就能正常运行):

  • TN_2025Q_V1.0.0.model3.json这是最重要的配置文件,是网页看板娘的“大脑”,它会告诉加载器如何使用其他所有文件。
  • TN_2025Q_V1.0.0.moc3:模型的核心骨骼和变形数据
  • texture_00.png, texture_01.png, texture_02.png:模型的纹理贴图(皮肤、衣服等)。

增强功能文件(有了这些,看板娘会更生动):

  • TN_2025Q_V1.0.0.physics3.json物理文件,负责让头发、尾巴、衣物等部位产生物理晃动效果。
  • motions/ 文件夹(虽然你没列出,但 model3.json 里几乎肯定会引用这个文件夹):里面应该包含了所有的动作文件.motion3.json),比如 idle(待机)、tap(点击)等动作。

其他文件(与网页看板娘无关,可忽略):

  • TN_2025Q_V1.0.0.model.moc:这是旧版 Live2D Cubism 3 的模型文件,新版使用 .moc3,这个文件可以忽略。
  • TN_2025Q_V1.0.0.cdi3.json参数定义文件,主要用于在 Live2D Cubism Editor 中编辑或在 Vtuber 软件中设置参数映射,网页端不需要。
  • TN_2025Q_V1.0.0.vtube.json:专门为 VTube Studio 软件生成的配置文件,包含参数映射、热键设置等,网页端不需要。
  • TN_2025Q_V1.0.0.xyplugin.json:可能是某个特定插件(如面捕插件)的配置文件,网页端不需要。
  • items_pinned_to_model.json, package.json:通常是模型编辑项目相关的元数据文件,网页端不需要。

使用 hexo-oh-my-live2d 插件来部署它的步骤。


核心步骤指引

  1. 安装插件:在你的 Hexo 博客根目录下,通过 npm 安装 hexo-oh-my-live2d 插件。
  2. 放置模型:将你拥有的整个模型文件包(包含 model3.json, moc3, png 等所有文件)放入博客目录中,例如 source/live2d_models/TN_Model/
  3. 配置插件:在 Hexo 的全局配置文件 _config.yml 中添加 OhMyLive2d 字段进行配置,关键是指定本地模型 path
  4. 部署验证:清理并重新生成博客,启动本地服务器查看效果。

详细操作步骤

步骤一:安装插件

在你的 Hexo 博客根目录下,打开终端(如 Git Bash),运行以下命令安装 hexo-oh-my-live2d 插件:

1
npm install hexo-oh-my-live2d

步骤二:整理并放置模型文件

  1. 在你的 Hexo 博客根目录下,创建一个专门存放模型的文件夹,例如 source/live2d_models/。这样做的好处是当执行 hexo generate 时,该文件夹内的内容会被复制到最终生成的静态网站中。

  2. 将你拥有的所有模型文件TN_2025Q_V1.0.0.model3.json, *.moc3, texture_00.png, texture_01.png, texture_02.png, 以及 motions 文件夹(如果提供的话)等)全部放入刚刚创建的 source/live2d_models/ 文件夹下的一个子文件夹中,例如命名为 TN_Model

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    你的博客目录/
    ├── source/
    │ └── live2d_models/
    │ └── TN_Model/
    ├── TN_2025Q_V1.0.0.model3.json
    ├── TN_2025Q_V1.0.0.moc3
    ├── TN_2025Q_V1.0.0.physics3.json
    ├── TN_2025Q_V1.0.0.cdi3.json
    ├── texture_00.png
    ├── texture_01.png
    ├── texture_02.png
    └── motions/
    └── idle.motion3.json
    ├── _config.yml
    └── themes/
    └── ayer/

⚠️ 非常重要:请确保 motions 文件夹(包含动作文件)和模型文件在同一目录下,且 TN_2025Q_V1.0.0.model3.json 文件中对这些资源的引用路径是正确的。通常模型师在导出时已经设置好,所以你只需保证所有文件都在同一个文件夹里即可。

步骤三:配置插件

打开 Hexo 博客的全局配置文件 _config.yml。通常位于博客的根目录下。

在文件的末尾,添加以下配置段落(注意: 这是 hexo-oh-my-live2d 的配置,不是旧的 hexo-helper-live2d 的配置):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
OhMyLive2d:
enable: true
CDN: https://unpkg.com/oh-my-live2d
option:
dockedPosition: 'left'
mobileDisplay: false # 改为false

# 尝试使用不同的Cubism版本(解决遮罩兼容性问题)
importType: 'cubism5' # 专门使用Cubism5版本
libraryUrls:
cubism5: https://registry.npmmirror.com/oh-my-live2d/latest/files/lib/cubism5.js

models:
- path: /live2d_models/TN_Model/TN_2025Q_V1.0.0.model3.json # 修正路径
position: [0, 50] # 调整位置
scale: 0.12 # 调整缩放比例(根据你的模型大小调整)
stageStyle:
width: 320
height: 400
mobilePosition: [0, 30]
mobileScale: 0.08
mobileStageStyle:
width: 200
height: 250
motionPreloadStrategy: IDLE # 改为IDLE,减少初始加载压力
expression: "默认表情" # 对应表情文件中的Name
# 或者直接指定文件
expressions:
- file: "表情.exp3.json"
name: "默认表情"

parentElement: document.body
primaryColor: 'var(--btn-bg)'
sayHello: false
tips:
style:
width: 230
height: 120
left: calc(50% - 20px)
top: -100px
mobileStyle:
width: 180
height: 80
left: calc(50% - 30px)
top: -100px
idleTips:
interval: 3600
message:
- 你好呀,我是你的看板娘~
- 欢迎来到我的博客~

创建基础动作文件

创建 motions 文件夹,并在其中创建 idle.motion3.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"Version": 3,
"Meta": {
"Duration": 10,
"Fps": 30.0,
"Loop": true,
"AreBeziersRestricted": true,
"CurveCount": 0,
"UserDataCount": 0,
"TotalSegmentCount": 0,
"TotalPointCount": 0,
"FadeInTime": 1.0,
"FadeOutTime": 1.0
},
"Curves": []
}

快速修复脚本

创建一个修复脚本 fix_model.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
const fs = require('fs');
const path = require('path');

// 读取模型文件
const modelPath = path.join(__dirname, 'source', 'live2d_models', 'TN_Model', 'TN_2025Q_V1.0.0.model3.json');
const modelData = JSON.parse(fs.readFileSync(modelPath, 'utf8'));

// 修复纹理路径
if (modelData.FileReferences && modelData.FileReferences.Textures) {
modelData.FileReferences.Textures = modelData.FileReferences.Textures.map(texturePath => {
return texturePath.replace('TN_2025Q_V1.0.0.4096/', '');
});
}

// 添加基础动作
if (!modelData.Motions) {
modelData.Motions = {
"idle": [
{
"File": "motions/idle.motion3.json"
}
]
};
}

// 保存修复后的文件
fs.writeFileSync(modelPath, JSON.stringify(modelData, null, 2));
console.log('模型文件修复完成');

// 创建motions文件夹和基础动作文件
const motionsDir = path.join(__dirname, 'source', 'live2d_models', 'TN_Model', 'motions');
if (!fs.existsSync(motionsDir)) {
fs.mkdirSync(motionsDir, { recursive: true });
}

const idleMotion = {
"Version": 3,
"Meta": {
"Duration": 10,
"Fps": 30.0,
"Loop": true,
"AreBeziersRestricted": true,
"CurveCount": 0,
"UserDataCount": 0,
"TotalSegmentCount": 0,
"TotalPointCount": 0,
"FadeInTime": 1.0,
"FadeOutTime": 1.0
},
"Curves": []
};

fs.writeFileSync(path.join(motionsDir, 'idle.motion3.json'), JSON.stringify(idleMotion, null, 2));
console.log('基础动作文件创建完成');

运行这个脚本:

1
node fix_model.js

测试修复结果

修复后,在浏览器控制台运行这个测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 测试修复后的模型
fetch('/live2d_models/TN_Model/TN_2025Q_V1.0.0.model3.json')
.then(response => response.json())
.then(modelData => {
console.log('修复后检查:');
console.log('纹理路径:', modelData.FileReferences.Textures);
console.log('是否有动作:', !!modelData.Motions);

// 测试纹理加载
modelData.FileReferences.Textures.forEach((texture, index) => {
fetch('/live2d_models/TN_Model/' + texture)
.then(response => {
console.log(`纹理 ${texture}: ${response.status === 200 ? '可访问' : '不可访问'}`);
})
.catch(error => {
console.log(`纹理 ${texture}: 加载失败`);
});
});
});

尝试不同的渲染引擎配置

在你的配置中尝试不同的Cubism版本:

1
2
3
4
5
6
7
8
OhMyLive2d:
enable: true
CDN: https://unpkg.com/oh-my-live2d
option:
# 尝试不同的导入类型
importType: 'complete' # 完整版本,兼容性最好
# importType: 'cubism5' # 或者尝试Cubism5专用版本
# importType: 'cubism2' # 或者尝试旧的Cubism2版本

加载表情文件

1.修改模型配置文件(推荐)

在你的 TN_2025Q_V1.0.0.model3.json 文件中添加表情文件引用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
{
"Version": 3,
"FileReferences": {
"Moc": "TN_2025Q_V1.0.0.moc3",
"Textures": [
"texture_00.png",
"texture_01.png",
"texture_02.png"
],
"Physics": "TN_2025Q_V1.0.0.physics3.json",
"DisplayInfo": "TN_2025Q_V1.0.0.cdi3.json",
// 添加表情文件引用
"Expressions": [
{
"Name": "默认表情",
"File": "表情.exp3.json"
}
]
},
"Groups": [
// ... 你现有的Groups内容 ...
],
"Motions": {
"idle": [
{
"File": "motions/idle.motion3.json"
}
]
},
// 添加表情配置
"Expressions": [
{
"Name": "默认表情",
"File": "表情.exp3.json"
}
]
}

2.通过插件配置加载表情

检查 oh-my-live2d 是否支持直接加载表情文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
OhMyLive2d:
enable: true
option:
models:
- path: /live2d_models/TN_Model/TN_2025Q_V1.0.0.model3.json
scale: 0.1
# 尝试通过配置加载表情
expression: "默认表情" # 对应表情文件中的Name
# 或者直接指定文件
expressions:
- file: "表情.exp3.json"
name: "默认表情"
display:
position: right

3.手动初始化模型参数

如果插件不支持直接加载表情,可以通过JavaScript在模型加载后手动应用表情:

创建一个自定义脚本文件 source/js/live2d-custom.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
document.addEventListener('DOMContentLoaded', function() {
// 等待Live2D加载完成
const checkLive2D = setInterval(function() {
if (window.OhMyLive2D && window.OhMyLive2D.instances.length > 0) {
clearInterval(checkLive2D);
applyExpression();
}
}, 500);

function applyExpression() {
const instance = window.OhMyLive2D.instances[0];

// 加载并应用表情文件
fetch('/live2d_models/TN_Model/表情.exp3.json')
.then(response => response.json())
.then(expression => {
console.log('加载表情文件成功', expression);

// 应用表情参数到模型
if (instance.model && instance.model.setExpression) {
instance.model.setExpression(expression);
} else {
// 如果插件没有暴露API,尝试直接设置参数
applyExpressionParameters(expression, instance);
}
})
.catch(error => {
console.error('加载表情文件失败:', error);
});
}

function applyExpressionParameters(expression, instance) {
// 手动应用表情参数
if (expression.Parameters && instance.model.coreModel) {
expression.Parameters.forEach(param => {
try {
instance.model.coreModel.setParameterValueById(param.Id, param.Value);
} catch (e) {
console.log('设置参数失败:', param.Id, e);
}
});
// 强制重绘
instance.model.update(0);
}
}
});

然后在主题布局文件中引入这个脚本。

依然存在的问题

解决了兼容性、配置等等的问题,依然绕不开模型过于无法无法使用的问题,于是这里放弃

  1. 模型使用了高级的遮罩功能(mask count 20-21),但当前渲染器不支持
  2. WebGL着色器程序设置失败,导致无法渲染模型
  3. hexo-helper-live2d(经典插件)也无法兼容

修改遮罩数量的可行性

需要的工具

  • Live2D Cubism Editor(官方编辑器,付费软件)
  • 或者 第三方工具(如社区开发的转换工具)

修改步骤(技术复杂)

  1. 使用Cubism Editor打开模型
    • 导入你的 .model3.json 文件
    • 在”蒙版”或”遮罩”设置中调整数量
    • 重新导出为网页兼容格式
  2. 技术挑战
    • 遮罩数量与模型复杂度直接相关
    • 减少遮罩可能导致渲染效果丢失
    • 需要重新调整材质和绘制顺序

如果确实需要修改模型,可以尝试:

  1. 使用Cubism Viewer(免费工具):
    • 下载Cubism Viewer
    • 导入模型查看基本兼容性
    • 尝试导出简化版本
  2. 在线转换服务
    • 搜索”Live2D模型转换”或”Live2D web兼容性转换”
    • 有些社区提供转换服务

最终备份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
OhMyLive2d:
enable: true
CDN: https://unpkg.com/oh-my-live2d
option:
# 尝试不同的导入类型
#importType: 'complete' # 完整版本,兼容性最好
# importType: 'cubism5' # 或者尝试Cubism5专用版本
# importType: 'cubism2' # 或者尝试旧的Cubism2版本
importType: 'cubism5' # 专门使用Cubism5版本
libraryUrls:
#complete: https://registry.npmmirror.com/oh-my-live2d/latest/files/lib/complete.js
#cubism2: https://registry.npmmirror.com/oh-my-live2d/latest/files/lib/cubism2.js
cubism5: https://registry.npmmirror.com/oh-my-live2d/latest/files/lib/cubism5.js
# 如果插件支持,添加渲染器配置
renderer:
type: 'pixi' # 或者 'webgl', 'canvas'

models:
- path: /live2d_models/TN_Model/TN_2025Q_V1.0.0.model3.json # 修正路径
position: [0, 50] # 调整位置
scale: 0.12 # 调整缩放比例(根据你的模型大小调整)
stageStyle:
width: 320
height: 400
mobilePosition: [0, 30]
mobileScale: 0.08
mobileStageStyle:
width: 200
height: 250
motionPreloadStrategy: IDLE # 改为IDLE,减少初始加载压力
expression: "默认表情" # 对应表情文件中的Name
# 或者直接指定文件
expressions:
- file: "馍馍.exp3.json"
name: "默认表情"

parentElement: document.body
primaryColor: 'var(--btn-bg)'
sayHello: false
tips:
style:
width: 230
height: 120
left: calc(50% - 20px)
top: -100px
mobileStyle:
width: 180
height: 80
left: calc(50% - 30px)
top: -100px
idleTips:
interval: 3600
message:
- 你好呀,我是你的看板娘~
- 欢迎来到我的博客~

另:live2D模型文件包打包到https://unpkg.com

核心条件:你的文件必须在一个 npm 包中

1
2
unpkg.com` 是一个为 **npm** 生态系统提供服务的 CDN。它的工作流程是:
`unpkg.com/:package@:version/:file
  • :package: npm 上的包名
  • :version: 包的版本号 (或 latest)
  • :file: 包内的具体文件路径

因此,最关键的一步是:你必须将你的 Live2D 模型文件发布到一个 npm 包中。

如果你没有 npm 账号,先去 npmjs.com 注册一个。


操作步骤

1. 准备你的 Live2D 模型文件和 package.json

创建一个新文件夹,例如 my-live2d-model

  1. 放入文件:将你的 Live2D 模型文件(如 .model3.json, .moc3, .png 等纹理文件, .physics3.json 等)放入这个文件夹。保持原有的文件结构非常重要,因为 JSON 文件中的路径是相对的。

  2. **创建 package.json**:在这个文件夹根目录下运行 npm init 并按照提示填写信息。或者手动创建一个 package.json 文件,内容最少需要包含:

    1
    2
    3
    4
    5
    6
    {
    "name": "my-live2d-model", // 取一个独一无二的包名,先在 npm 上搜索是否被占用
    "version": "1.0.0", // 版本号
    "main": "index.js", // 这个对于模型文件不是必须的,但必须要有。可以随便指向一个文件。
    "description": "My Live2D model package"
    }

    package.json

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    {
    "name": "tn2025q",
    "version": "1.0.0",
    "description": "My Live2D model package",
    "main": "index.js",
    "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
    },
    "keywords": [],
    "author": "",
    "license": "ISC"
    }

    你的目录结构应该看起来像这样:

    1
    2
    3
    4
    5
    6
    7
    8
    my-live2d-model/
    ├── package.json
    ├── shizuku.model3.json
    ├── shizuku.moc3
    ├── shizuku.physics3.json
    ├── textures/
    │ └── texture_00.png
    └── index.js (可选)

检查包名是否可用

在发布前,先检查包名是否可用:

1
npm view tn2025q

如果返回 404,表示包名可用;如果返回包信息,则需要选择其他名称。

2. 发布到 npm

  1. 在终端中,进入你的项目文件夹 my-live2d-model
  2. 运行 npm login 登录你的账号。
  3. 运行 npm publish 发布你的包。

发布成功后,你的包就可以在 npm 上搜索到了。

npm 包名必须符合以下要求

  • 包名长度应大于零
  • 所有字符必须是小写字母
  • 可以包含连字符、数字和下划线,但不能以它们开头或结尾
  • 不能包含任何非URL安全字符(因为包名会出现在URL中)
  • 不能与现有包名重复

3. 构建 unpkg URL

现在,你可以使用 unpkg 来访问你的文件了。

1
2
3
npm i tn2025q

npm install --save tn2025q

oh-my-live2d

在-hexo-中使用

https://zhuanlan.zhihu.com/p/98597931

https://mugaiashe.github.io/posts/82785c10.html

https://blog.phlin.cn/2024/08/25/live2d-using/

https://blog.empty-city.top/posts/de3e4889/index.html

https://makkishizu.github.io/2024/11/28/Live2D/

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

You Found Me.

支付宝
微信