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

本文介绍了如何在Unity中创建动画文件,使用BlendTree进行动画逻辑控制,特别是设置人物移动和方向切换的动画。通过创建浮点变量检测移动速度,结合混合树实现平滑的动画过渡,最后展示了如何保持移动方向的动画切换效果。

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

目录

创建动画文件

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

 创建移动变量

了解并使用混合树

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


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

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

创建动画文件

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

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

选中我们的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);


    }

}

来看看效果如何

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

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

 

### 如何在 Unity 中实现动画之间的平滑过渡或切换Unity 的 Animator 组件中,动画状态机提供了强大的功能来管理多个动画片段并实现在它们之间的平滑过渡。以下是关于如何配置和使用这些功能的具体说明。 #### 配置动画状态机以支持平滑过渡 Animator 提供了一个名为 **Transitions** 的特性,允许开发者定义两个动画状态间的转换逻辑以及过渡时间[^2]。为了确保动画切换不显得生硬,可以在 Transition 设置面板中调整 `Transition Duration` 参数。此参数决定了从当前动画到下一个动画所需的时间长度,从而达到自然的效果。 #### 使用脚本动态控制动画参数 通过调用 Animator 类的方法如 SetBool, SetInteger 和 SetFloat 来改变动画控制器中的布尔值、整数值或者浮点数变量的状态,进而触发相应的动画播放[^1]。例如: ```csharp animator.SetBool("isWalking", true); ``` 上述代码会依据设定好的条件激活行走动画。如果希望基于角色的速度决定是否进入跑步模式,则可采用如下方式更新速度参数: ```csharp float speed = CalculateSpeed(); animator.SetFloat("speed", speed); if (speed > runThreshold) { animator.SetBool("isRunning", true); } else { animator.SetBool("isRunning", false); } ``` 这里的 `CalculateSpeed()` 函数应返回实际计算得到的角色运动速率;而 `runThreshold` 是预先定义的一个阈值常量用来区分走动与奔跑两种情形。 #### 增强真实感——IK 动画的应用场景 对于更加复杂的交互需求比如人物拾取物品动作或是战斗姿态调整等情况,可以考虑引入逆向动力学(Inverse Kinematics, IK)[^3]。当启用 IK 后,在 LateUpdate() 方法里指定末端效应器的位置即可完成手部或其他部位精确指向目标位置的操作。 另外值得注意的是,某些特殊情况下可能还需要配合 Ragdoll 物理系统模拟尸体倒下过程等非主动行为表现形式。这通常涉及到禁用骨骼刚体约束并将关节连接替换为铰链链接的过程。 #### 更高级别的摄像机视图处理技巧 除了基本的对象内部动画外,外部观察角度的变化同样重要。借助 Cinemachine 插件能够轻松达成复杂镜头调度目的,相比单纯依靠 Camera 移位操作而言具备更多灵活性和可控度[^4]。 最后附上一段简单的初始化音频源及计时器设置实例作为补充参考资料[^5]: ```csharp void Start () { audioSource = GetComponent<AudioSource>(); animator = GetComponent<Animator>(); timerClip_Foot = 0.0f; timerClip_Hit = 0.0f; } ``` 以上就是有关于怎样在 Unity 当中执行动画间平稳过度变换的相关指导信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值