Unity教程3:使用BlendTree控制人物移动动画切换

目录

创建动画文件

移动动画逻辑以及BlendTree的使用方法

 创建移动变量

了解并使用混合树

实现保持移动方向的动画切换


手册链接在这:Unity User Manual (2019.3) - Unity 手册

实现了基本的人物移动代码后,为了使得我们的人物更加的生动有趣,我们还需要实现人物的动画效果。

创建动画文件

那么首先需要新建一个动画文件

首先点击Window选项卡,在下拉菜单中找到Animition选项,选择Animation,是后面带一个crtl+6的快捷键的,不要选成Animator了。

扫描二维码关注公众号,回复: 15204408 查看本文章

选中我们的Player,在弹出的组件窗口中选择Create

 然后Unity会询问你想要将动画文件放在哪里,那么这里不演示了,文件管理对于我们的游戏项目还是非常重要的,请妥善分类存放。

那么在新建一个动画文件后,看到的界面应该如下图所示。

 蓝色框选的是采样率,如果你的组件窗口中没有这个,请按照如下所示操作

点击这个

 然后勾选弹出选项中的:Show sample Rate 即可

然后将我们切割好的动画文件选中对应我们需要的动画拖放到窗口中

 点击Play会发现动画非常鬼畜,降低采样率即可,我这边设置采样率为5,不同的素材帧动画数量不同,可以自行调整。

这是如下idle动画产生的效果

 那么人物的待机动画就这么设置完毕了,接下来就是设置人物的上下左右移动动画和待机动画,步骤都是一致的,记得取好名字方便后序辨认,我在这里就不一一演示了。

那么创建好了动画文件,我们应该在哪实现我们的动画转换呢?这个时候就可以打开之前的Animator了,也就是我们的动画机。

 将我们刚才创建好的动画文件拖动到动画机内部即可得到一个动画节点

橙色的节点代表默认的节点,你可以随意的更改,不过idle肯定是默认的。

 使用鼠标中间和alt+鼠标左键即可拖动动画机内部的窗口。

动画与动画间的过渡可以通过建立转换条件来实现,如下图所示。

但是动画一多就会变成我这样的“盘丝洞”....;

可以看到,Unity的动画机本身提供了逻辑连线的方式切换动画,但是上图所示的方法非常的麻烦且冗杂,其具体的操作并不讨喜,在这里也就不记述了,所以为了更好的设置动画,我们使用非常方便的一个组件,BlendTree(混合树)。

移动动画逻辑以及BlendTree的使用方法

 创建移动变量

首先,我们人物的动画转换的逻辑就是移动的时候播放移动的动画,停止时播放idle动画,且移动的方向不同也对应了不同的动画。

那么我们的游戏中X和Y轴的移动需要被检测,那么我们设置两个浮点型参数,一个为Xspeed也就是水平速度,另一个Yspeed也就是垂直速度来代表我们人物的移动。

点击这个+号即可创建,选择float就是浮点型,int是整型,bool是只有True 或者 False的布尔型,还有一个检测是否发生互动的Trigger型。

 创建好这两个参数之后,我们后面就可以借助脚本来获取人物的移动速度了,并且根据这两个数值来播放对应的动画。

了解并使用混合树

 混合树的主要实现逻辑是根据开发者自己设置的参数权重来过渡动画,比如速度达到某个阈值时播放某个动画,其逻辑和连线动画机一样但是使用起来更加容易理解和操作,甚至非常好玩。那么接下来我们就来玩一玩这个神奇的混合树。

 我们新建一个混合树。双击混合树节点即可进入其内部设置

 我们先创建几个motion field(运动域),并拖动4个方向的移动动画上去

 我们的人物需要二维移动,所以我们需要更改条件,点击Blend Type置换成2D Simple Direction

然后取消勾选阈值

 设置好运动参数,也就是我们刚才设置好的水平速度和垂直速度。

 

 设置完毕后,拖动混合树中的红点即可在预览窗口看见我们人物不同位移权重下的移动动画切换效果。

 当然,添加更多的motion field 可以实现更多的方向!这个可以你可以自己试试!

现在还差最后一步了,也就是进入混合树的条件,毕竟这个设置只发生在混合树内部而非整个动画机,动画整体的控制依旧取决于我们的动画机。

我们回到Animator的层级,新建一个变量用于检测玩家输入了移动的数值,也就是移动的速度,然后添加一个切换条件为当movement变量大于0.1时进入混合树,其中切换条件不需要退出时间,将fixdiertion设置为0。

 当然进入了混合树我们希望它能回到idle的状态,那么再给一个返回条件。

 然后在我们的PlayerControler内部添加这段代码,设置动画机内部的值。


        anim.SetFloat("Yspeed", movement.y);
        anim.SetFloat("Xspeed", movement.x);
        anim.SetFloat("Movement", movement.sqrMagnitude);

添加在movement函数内部即可。

sqrMagnitude可以直接求取速度且没有求平方根的过程,算一个小优化,直接使用magnitude会有这个步骤。

保存代码回到Unity来测试一下效果

 效果很好!但是它每一次都会回到正向的idle动画显得不是很好,我希望他保持在当前停留的方向上,这该如何实现呢?

实现保持移动方向的动画切换

那么我们先整理逻辑,每当movement的值为0的时候动画机就会切换回idle,那么为了能让它保持播放当前最后一次操作所产生的速度变化,我们可以多创建两个值来保存,然后传入Xspeed或者Yspeed中。

我们先关闭能回到idle动画的条件,也就是把回去的那个条件删去,然后在我们的脚本文件中创建两个float类型的全局变量来持续保存我们的X或者Y轴上的速度变化

    float keepx = 0.0f;
    float keepy = 0.0f;

那么逻辑就是只要任意一个方向上的向量产生了变化,就记录下来,而非实时更新,那么x和y有正有负,对其取绝对值,只要大于0就是产生了变化,保存

       if (Mathf.Abs(movement.x) > 0 || Mathf.Abs(movement.y) > 0)
       {
           keepx = movement.x;
           keepy = movement.y;
       }

然后也要更改我们传入的参数名称

        anim.SetFloat("Yspeed", keepy);
        anim.SetFloat("Xspeed", keepx);

 保存代码回到Unity看看效果

 很棒!那么现在看起来还是有点别扭,因为我们还没有完成不同方向上的idle动画切换,那么接下来就来实现一下。

那么主要就是处理动和不动的时候的分别,那么我们新建一个blendTree来专门转换不动的时候的动画,然后借助我们前面保留地的数值来实现停留的idel动画切换

这里新的blendTree的创建和前文没有半毛钱区别,还请读者自己试试!然后就是代码逻辑问题,我们新建一个bool值用来判断是否移动,借助这个条件作为两颗混合树的切换条件,然后整体框架代码实现如下。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerControler : MonoBehaviour
{
    private Rigidbody2D rb;
    private Animator anim;
    new Transform transform;


    public float Movespeed;

    Vector2 movement;

    float keepx = 0.0f;
    float keepy = 0.0f;

    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        anim = GetComponent<Animator>();

    }

    // Update is called once per frame
    void Update()
    {
        
    }

    private void FixedUpdate()
    {
        Movement();
    }


    void Movement()
    {
        movement.x = Input.GetAxisRaw("Horizontal");
        movement.y=  Input.GetAxisRaw("Vertical");

        //只要任意一个方向上的向量产生了变化,就记录下来,而非实时更新
        if (Mathf.Abs(movement.x) > 0 || Mathf.Abs(movement.y) > 0)
        {
             keepx = movement.x;
             keepy = movement.y;
            anim.SetBool("isMove", true);
        }
        else//没有移动,isMove为假
        {
            anim.SetBool("isMove", false);
        }

        anim.SetFloat("Yspeed", keepy);
        anim.SetFloat("Xspeed", keepx);
        anim.SetFloat("Movement", movement.sqrMagnitude);

        rb.MovePosition(rb.position + movement * Movespeed*Time.fixedDeltaTime);


    }

}

来看看效果如何

 效果真的很好,而且操作简单易懂。

那么以上就是混合树的一个使用范例了,希望对你有点帮助,感谢阅读!

猜你喜欢

转载自blog.csdn.net/m0_53607711/article/details/129623852