在Unity中使用Live2d插件02 播放动画,动画优先级设置

继续01篇的内容,在unity中加载入小姐姐后,此时她还只是一张图片,并不会动,这时就需要引入配套的动画。

实例化动作对象 加载mtn文件

//这是直接加载mtn文件的方法
live2DMotionIdle = Live2DMotion.loadMotion(Application.dataPath + "");
//这是加载二进制文件的方法
TextAsset mtnFile = Resources.Load("");
live2DMotionIdle =  Live2DMotion.loadMotion(mtnFile.bytes);

定义一个TextAsset数组,用于存储动作的二进制文件,定义一个 Live2DMotion数组,用于存贮由二进制文件加载的动作 

这个动作的二进制文件由此得来:在Epsilon/Epsilon/runtime/motions下面有许多mtn文件,CTRLcv复制粘贴得到副本,在副本后面加上.bytes变为二进制文件,再从unity的inspector视口拖入。

public TextAsset[] motionFiles;

    //动作数组
private Live2DMotion[] motions;
 //将读入的motion文件加载入对应的Live2DMotion数组中
        motions = new Live2DMotion[motionFiles.Length];
        for (int i = 0; i < motions.Length; i++)
        {
            motions[i] = Live2DMotion.loadMotion(motionFiles[i].bytes);
        }

接下来可以单独设置每一个动画的属性

  //重复播放时是否淡入,动作跨度大设置可以看起来更自然 参数为bool
   motions[0].setLoopFadeIn(false);//重复播放不淡入
  //设置淡入淡出时间
  //淡出,不设置默认值也为1000毫秒。
   motions[0].setFadeOut(1000);
  //淡入
   motions[0].setFadeIn(1000);
  //设置动画是否循环播放
   motions[0].setLoop(true);

播放动画还需要一个动画队列的管理器,定义一个motionQueueManager对象

//动作管理队列,管理动画的播放
    private MotionQueueManager motionQueueManager;

使用startMotion设置播放的动画 

 motionQueueManager = new MotionQueueManager();
 //播放动画
 motionQueueManager.startMotion(motions[0]);

在update中更新状态,由于动画和模型是对应的,需要为管理器指定哪一个模型播放动画

  motionQueueManager.updateParam(live2DModel);

动画是可以叠加的,比如角色动嘴没动手时,可以为手指定动作,动头没动身体时,可以为身体指定动作,当动作冲突时取后指定的动作。需要同时播放几个动作就需要几个动画管理器


    //第二个动作管理,要同时播放几个动画就要有几个管理者
    private MotionQueueManager motionQueueManagerA;


//Start函数中
        motionQueueManager.startMotion(motions[0]);//第一个管理器
         motions[5].setLoop(true);
        motionQueueManagerA = new MotionQueueManager();//第二个管理器
        motionQueueManagerA.startMotion(motions[5]);



//Update函数中
       motionQueueManager.updateParam(live2DModel);
        motionQueueManagerA.updateParam(live2DModel);//同时更新两个管理器状态

这样模型就同时做出了第一个和第5个动作

在Unity中使用Live2d插件02 播放动画,动画优先级设置_第1张图片

在unity的animator组件中可以设置动画的状态机,同理live2d也可以设置状态机,不过使用的是代码实现

注释掉前面motionQueueManager的相关语句,改用状态机控制动画。

动画优先级分为四个:

优先级的设置标准 
    //1.动作未进行的状态,优先级为0
    //2.待机动作发生时,优先级为1
    //3.其他动作进行时,优先级为2
    //4.无视优先级,强制发生的动作

声明一下live2d框架的命名空间

using live2d.framework;

定义一个优先级管理器

   private L2DMotionManager l2DMotionManager;
//Start 函数里
 l2DMotionManager = new L2DMotionManager();

在update函数中 

        //优先级设置
        //判断待机动作,isFinished判断动作完毕否
        if (l2DMotionManager.isFinished())
        {
            StartMotion(0, 1);//0为idle动画,优先级是1
        }
        else if (Input.GetKeyDown(KeyCode.M))
        {
            StartMotion(14, 2);
        }
        //更新动作数据
        l2DMotionManager.updateParam(live2DModel);

当按下m时,传入一个优先级为2的动画,就会将当前idle动画进行切换

//播放动画的方法封装
    public void StartMotion(int motionIndex, int priority)
    {
        //getCurrentPriority()正在播放动画的优先级
        //与要播放的动画的优先级对比,同优先级或者大于要播放的动画的优先级,不操作
        if (l2DMotionManager.getCurrentPriority()>= priority)
        {
            return;
        }
        //要播放的动画优先级比现在的大
        l2DMotionManager.startMotion(motions[motionIndex]);
    }

这样就设置出了一个简易的状态机,当不操作时模型一直播放idle动画,按下m后播放14动画,播放完毕后又回到idle状态

完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using live2d;
using live2d.framework;
public class Live2dModel : MonoBehaviour {

    public TextAsset modelFile;

    private Live2DModelUnity live2DModel;
    public Texture2D[] textures;
    public TextAsset[] motionFiles;
    //动作优先级管理
    //优先级的设置标准 
    //1.动作未进行的状态,优先级为0
    //2.待机动作发生时,优先级为1
    //3.其他动作进行时,优先级为2
    //4.无视优先级,强制发生的动作
    private L2DMotionManager l2DMotionManager;

    //动作数组
    private Live2DMotion[] motions;

    //动作管理队列,管理动画的播放
    private MotionQueueManager motionQueueManager;

    //第二个动作管理,要同时播放几个动画就要有几个管理者
    private MotionQueueManager motionQueueManagerA;

    //动作索引
    public int motionIndex;

    //live2d的画布
    private Matrix4x4 live2dCanvasPos;
    //动作对象
    //private Live2DMotion live2DMotionIdle;

	// Use this for initialization
	void Start () {
        //初始化环境  使用环境前一定要调用一次  连续调用/不调用会出错
        //可以释放后再次初始化重新使用
        Live2D.init();

        //释放环境 没有初始化是不能释放的
        //Live2D.dispose();

        //1.读取模型 
        //Live2DModelUnity专门负责模型的加载
        //加载moc文件一定要有.moc后缀
        //加载moc↓
        //Live2DModelUnity.loadModel(Application.dataPath + "/Resources/Epsilon/Epsilon/runtime/Epsilon.moc");  //二进制文件或者moc文件路径
        //加载二进制文件  复制moc文件,在副本文件名后面加上.bytes后缀变为二进制文件
        //使用textAsset接收二进制文件
        //加载二进制 ↓
        //TextAsset mocFile = Resources.Load("Epsilon/Epsilon/runtime/Epsilon.moc");
        //Live2DModelUnity.loadModel(mocFile.bytes);
        //方法返回一个类型为Live2DModelUnity的模型对象,对应于加载的这个模型
         live2DModel =  Live2DModelUnity.loadModel(modelFile.bytes);

        //2.联系贴图
        //只能通过路径读取
        //Texture2D texture2D = Resources.Load("Epsilon/Epsilon/runtime/Epsilon.1024");
        //live2DModel.setTexture(0, texture2D);
        //设置贴图  前一个参数是贴图序号,由建模师决定
        //设置多张贴图
        //Texture2D texture2D1 = Resources.Load("Epsilon/Epsilon/runtime/Epsilon.1024/texture_00");
        //Texture2D texture2D2 = Resources.Load("Epsilon/Epsilon/runtime/Epsilon.1024/texture_01");
        //Texture2D texture2D3 = Resources.Load("Epsilon/Epsilon/runtime/Epsilon.1024/texture_02");
        //live2DModel.setTexture(0, texture2D1);
        //live2DModel.setTexture(1, texture2D2);
        //live2DModel.setTexture(2, texture2D3);

        for (int i = 0; i < textures.Length; i++)
        {
            live2DModel.setTexture(i, textures[i]);
        }

        //3与绘图环境建立链接(unity不需要)
        //4指定显示位置与尺寸
        //定义画布 Matrix4x4 live2dCanvasPos;
        //创建正交的投影矩阵 参数是左右上下近视口远视口
        float modelWidth = live2DModel.getCanvasWidth();
        //+-50由官方提供
        //将相机设置为正交相机
        live2dCanvasPos = Matrix4x4.Ortho(0, modelWidth, modelWidth, 0, 50, -50);

        //播放动作
        //实例化动作对象 加载mtn文件
        //live2DMotionIdle = Live2DMotion.loadMotion(Application.dataPath + "");
        //TextAsset mtnFile = Resources.Load("");
        //live2DMotionIdle =  Live2DMotion.loadMotion(mtnFile.bytes);
        //将读入的motion文件加载入对应的Live2DMotion数组中
        motions = new Live2DMotion[motionFiles.Length];
        for (int i = 0; i < motions.Length; i++)
        {
            motions[i] = Live2DMotion.loadMotion(motionFiles[i].bytes);
        }
        /*
        //设置动画的属性
        //重复播放时是否淡入,动作跨度大设置可以看起来更自然 参数为bool
        motions[0].setLoopFadeIn(false);//重复播放不淡入
        //设置淡入淡出时间
        //淡出,不设置默认值也为1000毫秒。
        motions[0].setFadeOut(1000);
        //淡入
        motions[0].setFadeIn(1000);
        //设置动画是否循环播放
        motions[0].setLoop(true);

        motionQueueManager = new MotionQueueManager();
        //播放动画
        motionQueueManager.startMotion(motions[0]);
        //动画的重叠
        motions[5].setLoop(true);
        motionQueueManagerA = new MotionQueueManager();
        motionQueueManagerA.startMotion(motions[5]);*/

        //动作的优先级使用
        l2DMotionManager = new L2DMotionManager();
    }
	
	// Update is called once per frame
	void Update () {
        //设置矩阵  两个矩阵相乘   
        //localToWorldMatrix局部转世界
        live2DModel.setMatrix(transform.localToWorldMatrix * live2dCanvasPos );
        //更新顶点,贴图等

        //按M更改动画
        //if (Input.GetKeyDown(KeyCode.M))
        //{
        //    motionIndex++;
        //    if(motionIndex >= motions.Length)
        //    {
        //        motionIndex = 0;
        //    }
        //    motionQueueManager.startMotion(motions[motionIndex]);
        //}

        ////指定哪一个模型播放动画
        //motionQueueManager.updateParam(live2DModel);
        //motionQueueManagerA.updateParam(live2DModel);

        //优先级设置
        //判断待机动作,isFinished判断动作完毕否
        if (l2DMotionManager.isFinished())
        {
            StartMotion(0, 1);//0为idle动画,优先级是1
        }
        else if (Input.GetKeyDown(KeyCode.M))
        {
            StartMotion(14, 2);
        }
        //更新动作数据
        l2DMotionManager.updateParam(live2DModel);


        live2DModel.update();
    }
    //绘图方法
    private void OnRenderObject()
    {
        live2DModel.draw();
    }
    //播放动画的方法封装
    public void StartMotion(int motionIndex, int priority)
    {
        //getCurrentPriority()正在播放动画的优先级
        //与要播放的动画的优先级对比,同优先级或者大于要播放的动画的优先级,不操作
        if (l2DMotionManager.getCurrentPriority()>= priority)
        {
            return;
        }
        //要播放的动画优先级比现在的大
        l2DMotionManager.startMotion(motions[motionIndex]);
    }
    
}

 

你可能感兴趣的:(Unity3D)