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

本文详述了Live2D模型与素材的导入流程,包括SDK接入、模型读取、贴图关联、动作与表情加载、模型参数设置及物理效果实现。介绍了如何在Unity中使用Live2D,实现模型的动态展示与互动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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]);
        }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

03-22
<think>好的,我现在需要处理用户关于Live2D的查询。首先,用户想了解Live2D的相关信息或使用方法,特别是使用教程和技术文档。根据用户提供的引用内容,有三个引用来源,我需要仔细分析这些引用,看看它们提供了哪些有用的信息。 首先看引用[1],里面提到了如何在Vue项目中引入Live2D看板娘,使用了`Live2d`组件,并导入了一个特定的路径。这可能涉及到前端框架中集成Live2D的方法,比如Vue组件。用户可能需要知道如何在自己的Vue项目中添加Live2D模型,所以这部分应该作为Vue集成的步骤之一。 引用[2]是关于Pixi-Live2D的使用教程,项目地址是pixi-live2d的GitCode镜像。这里提到的是在pixi.js中使用Live2D模型作为精灵显示。Pixi.js是一个2D渲染引擎,常用于游戏和交互式应用,所以用户可能想知道如何在游戏或Web应用中嵌入Live2D模型。这里需要说明使用Pixi.js的步骤,可能包括安装库、加载模型等。 引用[3]指向另一个修改版的Live2D项目,基于hexo-helper-live2d,适用于Hexo博客统。项目地址是live2d_src,这可能帮助用户在静态博客中添加Live2D角色。Hexo用户可能需要这样的插件来增强博客的互动性,所以需要介绍如何在Hexo中配置和使用该插件。 接下来,我需要将这些信息整理成结构化的回答。用户的问题包括使用教程和技术文档,因此我应该分不同场景来说明,比如Web前端、游戏开发(使用Pixi.js)、Hexo博客集成,以及官方资源。每个部分需要简明扼要地说明步骤,并引用对应的来源。 同时,用户可能对各个项目的安装、配置步骤以及示例代码感兴趣,需要提供具体的代码片段,如Vue组件引入、Pixi.js初始化模型、Hexo插件配置等。此外,官方文档和社区资源也是重要部分,应该给出链接方便用户进一步查阅。 还需要生成相关问题,可能涉及技术选型、模型创建、性能优化、常见问题解决等,这些可以帮助用户深入探索Live2D的不同方面。例如,如何选择适合的集成方式,如何制作自己的Live2D模型,如何优化性能,如何解决加载问题等。 在整理过程中,要确保遵循用户的格式要求:行内数学公式用$...$,独立公式用$$...$$,但当前内容可能不涉及数学公式,所以可能需要忽略这点。另外,回答必须用中文,结构清晰,分步骤说明,引用标识自然添加在段落末尾。 最后,检查是否有遗漏的信息,比如引用中的项目地址是否正确,步骤是否清晰,是否覆盖了用户可能需要的不同使用场景。确保每个部分都有对应的引用标注,例如在Vue部分标注[^1],Pixi.js部分标注[^2],Hexo部分标注[^3],以及官方资源部分可能没有引用来源,但如果有其他引用也需要标注。</think>### LIVE2D 使用教程与技术文档 LIVE2D 是一种基于2D图像的动态渲染技术,广泛应用于虚拟角色动画、游戏、网页互动等领域。以下是不同场景下的使用方法和资源整理: --- #### 1. **Web前端集成(Vue项目)** 在Vue项目中,可通过组件化方式引入LIVE2D看板娘: ```javascript // 引入组件 import Live2d from '../components/live2d/index.vue' export default { components: { Live2d } } ``` 在模板中直接使用 `<Live2d />` 标签即可展示模型[^1]。需确保模型文件路径正确,并配置好动画参数。 --- #### 2. **游戏开发(Pixi.js集成)** 使用 **pixi-live2d** 库可将LIVE2D模型作为精灵嵌入Pixi.js渲染引擎: ```javascript import { Live2DModel } from 'pixi-live2d'; async function loadModel() { const model = await Live2DModel.from('model.json'); app.stage.addChild(model); // app为Pixi.Application实例 } ``` 项目地址:[pixi-live2d GitCode镜像](https://gitcode.com/gh_mirrors/pi/pixi-live2d)。 --- #### 3. **Hexo博客插件** 通过 **hexo-helper-live2d** 插件可在Hexo静态博客中添加动态角色: 1. 安装插件: ```bash npm install hexo-helper-live2d ``` 2. 在Hexo配置文件中添加: ```yaml live2d: enable: true model: chitose # 默认模型名称 display: position: right ``` 修改版项目地址:[live2d_src](https://gitcode.com/gh_mirrors/li/live2d_src)。 --- #### 4. **官方资源与文档** - **技术文档**:参考[LIVE2D Cubism SDK](https://www.live2d.com/en/download/cubism-sdk/),包含模型制作、动画绑定、SDK接入指南。 - **模型商店**:[LIVE2D Marketplace](https://www.live2d.com/en/market/) 提供付费/免费模型资源。 ---
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值