
简介这是一份面向Web前端开发者和网页交互设计爱好者的Live2D技术示例包用于解决如何在HTML页面中集成“看板娘”角色、实现角色动画与触摸反馈等互动效果的问题。压缩包内共506个文件大小约38.7MB主要包含17个Live2D模型及对应moc模型文件、json配置、265个mtn动作文件以及116个mp3和35个wav音频资源用于各模型的触发音效与反馈同时附有html、js、css示例页面文件可直接查看前端调用Live2D的基础结构。资源尤其适合希望从零了解Live2D Cubism SDK接入流程、熟悉模型加载与事件处理的中级前端开发者。包内模型风格多样涵盖了不同触摸反馈和动画表现便于对照分析配置差异。目前已吸引2263人学习浏览值得下载后结合本地部署或开发服务器运行以完整体验各项交互效果。1. 拿到 live2d.zip 之后你要的其实是「能跑的模型」不是压缩包很多刚接触 Live2D 的人第一次拿到手的资源都是一个叫live2d.zip的压缩包里面可能是一套模型文件、可能是一个项目工程、也可能只是从某个游戏里扒出来的立绘加动作数据。这个标题真正的价值不在「解压」这一下而在于你拿到 zip 之后怎么把它变成网页上能动的、能交互的看板娘或角色。我最早是在给一个个人站点做首页装饰时拿到的这种包当时以为解压完就能用结果打开全是.moc3、.model3.json、一堆.png和.motion3.json。那一瞬间是懵的。后来花了一晚上搞清楚整个资源结构和加载链路才发现 Live2D 这东西说白了就三件事模型文件、运行时Cubism SDK、渲染入口。这篇就把「从 zip 到能动的模型」这条路完整走一遍涵盖解压后怎么识别结构、怎么在网页里最小化跑通、参数怎么调、以及那些不试不知道的坑。2. 解压与识别资源结构先分清「模型包」和「工程包」2.1 为什么一上来要先分类型live2d.zip这个名字太宽泛了。我收过十来个不同来源的包里面的内容大致能分成三类模型包以.model3.jsonCubism 4或.model.jsonCubism 2为核心旁边跟着贴图.png、动作.motion3.json、表情.exp3.json物理模拟文件.physics3.json可能也有。这类包是最常见的直接能被运行时加载。工程包里面是.cmo3文件Cubism Editor 的工程文件旧版是.cmo可能还有Assets目录、Live2DModel目录之类的。这种包不能直接在网页里用得先在 Cubism Editor 里重新导出成模型包。混合包既有.cmo3工程也有导出的模型文件。这种通常是作者打包时没挑直接全扔进去了。用的时候只取模型包部分就行。判断方法很简单解压后先看有没有.model3.json或.model.json。有就是模型包只有.cmo3就是工程包两者都有用前者。2.2 用命令行快速摸清包内结构Windows 上我习惯先把 zip 拷到一个干净目录然后用tar解压Windows 10 1803 之后自带不需要额外装解压软件mkdir C:\tmp\live2d_work cd C:\tmp\live2d_work tar -xf D:\downloads\live2d.zip dir /s /b *.model3.json *.model.json第二步列出所有模型定义文件一眼就能看到包里有哪几个可用模型。如果有多个.model3.json说明一个包里塞了多套模型后面加载时挑一个就行。dir /s /b是 Windows 的递归列文件命令*.model3.json的匹配方式在 cmd 里没问题但在 PowerShell 里dir是Get-ChildItem的别名参数会不一样。所以我一般直接用cmd /c dir /s /b *.model3.json或者在 PowerShell 里用Get-ChildItem -Recurse -Filter *.model3.json。macOS / Linux 下更直接unzip live2d.zip -d live2d_work find live2d_work -name *.model3.json -o -name *.model.json这里-o是find的「或」逻辑注意-name条件的括号优先级不加括号的话-o后面的条件单独成组可能导致只搜到.model.json而漏掉.model3.json。稳妥写法是find live2d_work \( -name *.model3.json -o -name *.model.json \)。解压完这一步包里有没有能用的模型、有几个基本就清楚了。如果是工程包接下来不是写代码而是去下 Cubism Editor 重新导出——这一步不在本文范围但需要记住工程包不能直接进网页别花时间在浏览器里找一个.cmo3的加载方式不存在这条路。2.3 把「纯模型文件」从包里挑出来确定是模型包之后我一般会把该模型的核心文件单独拷到一个新目录避免后面开发时路径混乱。一个标准的 Cubism 4 模型包通常长这样my_model/ my_model.model3.json my_model.physics3.json my_model.exp3.json my_model.motion3.json textures/ texture_00.png texture_01.png motions/ idle.motion3.json tap.motion3.json复制时只拷运行时要用的部分*.cmo3、*.cdi、*.moc旧版有时也有这些要么不需要、要么得靠编辑器转。注意.moc3文件通常是和.model3.json同名的这个文件是模型的几何数据核心少了它模型直接废掉。3. 在网页里跑通第一个 Live2D 模型最小依赖组合3.1 为什么选 PixiJS pixi-live2d-display网页端跑 Live2D 的常见方案有两条路官方 Cubism SDK for Web原生写起来非常啰嗦或者社区封装层的pixi-live2d-display。我强烈建议新手直接走后者。原因有三PixiJS 渲染管线帮你处理了贴图、变换、帧循环你不用自己管 WebGL 的初始化细节。pixi-live2d-display把模型生命周期封装成 PixiJS 的显示对象addChild就能显示和写普通 2D 精灵图一样。这层抽象价值很大因为 Cubism 模型内部有「参数」系统眼睛睁开、视线方向、身体晃动没这层封装你得手动拉Live2DModel的 update 循环。社区示例多踩坑答案能找到。遇到白屏、模型不动、贴图错位搜索基本能命中。需要注意Cubism 有版本分裂问题Cubism 2.moc/.model.json和 Cubism 4.moc3/.model3.json的文件格式和运行时 API 完全不同。pixi-live2d-display的cubism4入口对应新版cubism2入口对应旧版别用混了。3.2 最小 HTML 启动文件下面是一个能在本地直接跑通的最小 HTML。我故意不引入构建工具双击就能看效果方便先验证模型文件本身是好的。!DOCTYPE html html langzh-CN head meta charsetUTF-8 titleLive2D Zip 快速验证/title style html, body { margin: 0; height: 100%; overflow: hidden; background: #f5f5f5; } #app { width: 100vw; height: 100vh; } /style /head body div idapp/div !-- 1. PixiJS 核心渲染引擎 -- script srchttps://cdn.jsdelivr.net/npm/pixi.js7/dist/pixi.min.js/script !-- 2. Cubism 4 运行时pixi-live2d-display 依赖它 -- script srchttps://cdn.jsdelivr.net/npm/pixi-live2d-display0.4.0/dist/cubism4.min.js/script script // 把 Live2D 的扩展混入 PixiJS之后才能 new Live2DModel PIXI.live2d Live2D; (async function () { const app new PIXI.Application({ view: document.getElementById(app), autoStart: true, resizeTo: window, backgroundAlpha: 0, antialias: true }); // 加载 model3.json —— 它是模型的总入口文件 const model await PIXI.live2d.Live2DModel.from(my_model/my_model.model3.json); app.stage.addChild(model); // 把模型放在舞台中央按下不表这里模型原始尺寸可能偏大 model.anchor.set(0.5, 0.5); model.position.set(app.screen.width / 2, app.screen.height / 2 50); // 让模型自动进入 idle 待机动画并开启自动呼吸/眨眼 model.state idle; model.autoInteract true; })(); /script /body /html逻辑拆开看就是四步初始化 PixiJS 应用、用Live2DModel.from异步加载模型总入口文件、把模型addChild到舞台、再设置位置和初始状态。from返回的是 Promise所以外层用了async/await。如果不等它加载完就继续执行model是空的后续设置全都会报错。参数说明anchor.set(0.5, 0.5)是把模型的锚点定位基准移到模型正中心这样position.set设置的就是中心点坐标resizeTo: window让画布撑满窗口不然内建默认 800x600 会出现大片空白antialias: true对 Live2D 这种大量矢量曲线的模型非常关键不开的话边缘锯齿明显。# 本地起一个静态服务推荐用 npx避免全局安装 cd C:\tmp\live2d_work npx http-server -c-1 -p 8080这里不是「双击 HTML 打开」而是起 HTTP 服务再访问因为Live2DModel.from内部走的是fetchfile://协议下浏览器会拦截跨文件读取导致模型加载失败。-c-1是关闭缓存每次刷新都能拿到最新文件——这个选项在你反复改模型文件时非常重要浏览器默认缓存经常让你以为没改对。3.3 模型不显示时的二分钟定位法首次跑通时最容易遇到的情况就是白屏。不要慌按这个顺序排查打开浏览器控制台F12看 Network 面板里有没有红字请求。如果my_model.model3.json返回 404说明路径写错了注意当前页面 URL 和模型目录的相对关系。如果文件返回 200 但页面还是白屏看 Console 报错——最常见的两种TypeError: Cannot read properties of undefined八成是 Cubism 运行时没加载成功检查cubism4.min.js的 script 标签有没有被浏览器拦截CDN 偶尔会抽风另一种是Failed to fetch那就是本地服务没起或者端口不对。还有一个玄学点模型文件里如果有中文文件名或路径某些浏览器在 fetch 时会有编码问题。我遇到过一次贴图路径带中文导致贴图加载不出来整个模型是透明的——因为模型画出来了只是贴图没了。解决办法是给模型文件和贴图全部用英文重命名并在model3.json里同步改引用路径。4. 参数调节与集成分层从「能跑」到「跑得自然」4.1 三个必调的视觉参数模型显示出来只是第一步。下面三个参数基本每次都要调。// 缩放模型原始设计尺寸通常在 2048x2048 甚至更大网页上必须压缩 model.scale.set(0.25, 0.25); // 或者等比例model.scale.set(0.25); // 位置微调不同模型的脚底坐标基准不一致需要试出来 model.position.set(app.screen.width / 2, app.screen.height / 2 50); // 透明度如果你要把模型叠在页面上而不是独立页面 model.alpha 0.95;scale是最容易理解也最容易翻车的参数——不同模型包的原始画布尺寸差异很大有的设计分辨率是 2048有的是 4096同样的 0.3 倍缩放前一个模型占屏幕一半后一个只占四分之一。没有捷径就是拖一个滑块实时看效果确定后写死。anchor和position组合决定模型站在哪。官方模型一般原点是脚底中央但社区模型很多是画布中心为原点直接position.set(centerX, centerY)会导致模型「悬浮」或「半身出屏」。我一般会先anchor.set(0.5, 0.5)再看不行再改用anchor.set(0.5, 1.0)让脚底对齐。4.2 交互触发tap 和 motion 的正确写法Live2D 模型内置「触摸交互」和「随机 idle 动作」这在看板娘场景里是灵魂。用pixi-live2d-display实现很简单但有几个细节容易做错。// 点击模型时播放指定动作 model.on(hit, (hitAreaName) { console.log(hit area:, hitAreaName); if (hitAreaName body) { model.motion(tap_body); } }); // 注册一个自定义参数标签控制模型朝向 model.on(custom, (name, value) { console.log(custom param:, name, value); });hit事件的回调参数hitAreaName来自模型内的命中判定区域。Cubism Editor 里可以给模型划分多个区域头、身体等hitAreaName就是那些区域的标签。如果你的模型没有划分命中区域点击不会触发hit事件这不是代码问题是模型本身的问题。更稳定的做法是直接用 PointerEvent 监听model.on(pointerdown, (e) { model.focus(e.data.global.x, e.data.global.y); model.motion(tap); });focus是让模型视线跟随鼠标坐标——这其实是 Live2D 最讨喜的效果不需要额外配置运行时自带。motion(tap)播放名为tap的动作名称来自模型包里的 motion 文件定义。如果模型包的动作文件名叫tap.motion3.json那么model.motion(tap)就能直接匹配不是这个名就报错或静默失败看控制台警告。4.3 三种集成场景的取舍集成到真实项目时有三种常见节奏场景推荐方式理由个人博客/简单页面单 HTML 引 CDN无构建零成本模型文件放本地或 OSS 都行Vite / Webpack 前端工程npm 安装pixi.js和pixi-live2d-display依赖版本可控生产环境打包后体积更优纯原生 JS 老项目保留 CDN 全局PIXI.live2d最省事不需要改造现有模块体系npm 方式的核心就一句话import { Live2DModel } from pixi-live2d-display但这时候必须确认 Cubism 运行时怎么引——有的版本需要单独import * as PIXI from pixi.js再混入Live2DModel不装pixi/live2d-display的老版本方案已经失效注意看包版本。这块我踩过一次坑npm 装的pixi-live2d-display默认指向 cubism2加载.model3.json时报错说文件格式不对。解决方法是把入口改成pixi-live2d-display/extra/cubism4或者显式引入cubism4.min.js。5. 常见问题避坑模型不动、贴图失踪、动作失灵的 5 个真实案例5.1 模型加载成功但完全不动现象贴图出来了模型也显示了但像一张壁纸一样静止。原因大多数模型的「待机动画」不是模型自带的是需要你用model.state idle或者手动播放 motion 才触发。还有一种是物理模拟文件缺失physics3.json找不到时模型失去所有轻微晃动看起来像冻住了。解决先确认model.state设置没有写错再检查my_model.physics3.json是否存在如果存在确认model3.json里的Physics字段路径正确。控制台若有Failed to load physics警告就是物理文件的问题。5.2 贴图加载不出来模型变成「透明人」现象模型几何还在能点击但看不到外观或者部分贴图缺失出现一些奇怪的条纹。原因.model3.json里的Textures数组路径写的是相对路径如果你的文件结构挪过路径就断了。另外前面提过的中文字符路径在部分浏览器里直接加载失败。解决用浏览器 Network 面板查贴图请求状态。404 就是路径错直接看请求 URL 与实际路径差异如果是中文路径统一改成拼音或英文全局搜一遍texture_00.png等文件名确认没有大小写不一致——Cubism 生成的贴图文件是区分大小写的Texture_00.png和texture_00.png是两个文件。5.3 每次关闭页面控制台就报错现象功能正常但页面关掉时 Console 刷一堆红色报错像是内存泄漏。原因PixiJS 的Application没有正确销毁模型的事件监听器还挂在 window 上。解决在页面卸载前调用app.destroy(true)同时把model的引用置空window.addEventListener(beforeunload, () { app.destroy(true, { children: true }); });第二个参数{ children: true }会递归销毁舞台上的子对象漏掉这个的话模型贴图对应的 GPU 纹理不会释放。5.4 换了模型包加载报错旧模型还能用现象新拿到的live2d.zip替换旧模型后页面直接白屏但原来那个模型是好的。原因八成是 Cubism 版本混用了。旧模型是 Cubism 2.model.json.moc新模型是 Cubism 4.model3.json.moc3而你的页面入口是dist/cubism4.min.js只能处理新格式。反过来页面入口是cubism2.min.js而包是.model3.json也是同样报错。解决确认模型格式后再决定用哪个入口脚本。同时模型包内如果同时存在.moc和.moc3以.model3.json为准说明作者导出了新版直接用新版旧文件删掉避免路径扫描混乱。5.5 模型在本地正常上线后部分文件 404现象本地http-server一切正常部署到服务器或对象存储后模型变形或贴图丢失。原因部署工具或平台对文件名大小写的处理方式不同。本地文件系统大小写不敏感macOS / Windows 默认但 Linux 服务器大小写敏感。如果模型内部引用了Texture_00.PNG而实际文件叫texture_00.png本地没问题一上 Linux 就暴露。解决部署前用 Linux 环境的容器或 CI 脚本校验一遍文件路径写个简单脚本把所有引用路径和真实文件名做大小写精确比对。遇到不一致就批量重命名——改文件名和改model3.json里的引用两边同步。提示上面这些坑里5.2 和 5.5 占了我碰到的 Live2D 问题的六成以上。路径问题永远是第一优先检查项代码逻辑反而很少出错。6. 进阶用法把模型「塞」进页面角落而不是全屏舞台最后讲一个实际使用中最高频的场景网页右下角的浮动看板娘。很多人的诉求不是全屏展示而是模型站在那里陪你浏览页面。关键是「穿透事件」和「固定层叠顺序」。// 把 canvas 变成“只能看不能摸”鼠标操作全部穿透到下层页面 app.renderer.plugins.interaction.autoPreventDefault false; document.getElementById(app).style.pointerEvents none; // 但模型本身要能响应点击恢复对模型的交互 model.interactive true; model.on(pointerdown, () { model.motion(tap); });pointerEvents: none是核心技巧——它让整个 Live2D canvas 不拦截任何鼠标事件页面下方的链接、滚动条全部正常使用但模型是 canvas 的一部分设置了interactive true后点击模型时事件仍然会触发模型动画这是因为interactive是 PixiJS 内部的事件开关不受 CSS 的pointer-events影响。反过来如果你发现点击模型后底下的页面元素也被误点就把pointerEvents改成auto或者干脆不做穿透。另一个实际技巧是控制模型加载时机避免阻塞页面首屏渲染window.addEventListener(load, () { PIXI.live2d.Live2DModel.from(my_model/my_model.model3.json).then((model) { // 这里初始化 }); });load事件等所有静态资源加载完才触发比DOMContentLoaded晚但更保险。如果你把模型加载放在DOMContentLoaded页面主体内容还没渲染完模型就抢占了带宽和 GPU 资源首屏速度会变慢。对于博客这种轻量页面延迟几百毫秒加载模型对体验的影响几乎为零。最后关于「有了 AI 是不是以后不用 Live2D 了」这个问题——不管以后技术怎么变「把动画角色以低门槛嵌入网页」这个需求长期存在。我现在的习惯是每次下载完live2d.zip先做一次「解压 → 识别类型 → 本地最小验证 → 重命名标准化」四步动作确保任何包到我手里都是即拿即用的状态。这个习惯帮我在后面至少三四个项目里避免了重复踩坑。希望这篇能帮你把这套流程也建立起来。本文还有配套的精品资源点击获取