Unity入门计划Unity2D动画-脚本与混合树实现玩家角色动画过渡

Posted 九九345

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity入门计划Unity2D动画-脚本与混合树实现玩家角色动画过渡相关的知识,希望对你有一定的参考价值。

目录

1 玩家角色移动伴随的简单动画 

1.1 行走

1.2 停留

1.3 攻击敌人(触发型)

1.4 受伤(触发型)

1.5 跳跃

1.6 下蹲

2 动画间的过渡

3 过渡的判断逻辑

3.1 行走与停留:移动速度

3.2 受伤&攻击:bool变量

4 根据实例展示Blend Tree与脚本的协作

4.1 在状态机中创建BlendTree

4.2 创建连接:Make Transition

4.3 创建所需变量并在Transition中加入逻辑

4.4 搭建每个混合树变量与Motion的关系

4.5 脚本中加入玩家键盘控制与角色动作的逻辑关系

1 获取动画组件

2 定义变量

3 Update()中定义当前变量与BlendTree变量相关联的逻辑

4 在脚本中关联bool变量Hit

5 效果展示

5 涉及到的Unity中C#用法

5.1 animator.SetTrigger/SetFloat

5.2 .Set()

5.3 .magnitude

5.4 .Normalize()

5.5 Mathf.Approximately()

5.6 new


学习的教程

【unity2021入门教程】80-2D游戏开发教程系列-03-RubyAdventure2DRpg官方教程-28-添加Ruby动画控制脚本_哔哩哔哩_bilibili

本篇博客依旧是建立在RubyAdventure项目上来写的,2D动画内容很多、覆盖面很广,因此以下局的一些动画例子几乎都是这个项目里涉及到的,没办法涵盖完全,以后有机会会补充清楚,这里就先围绕着Ruby角色的动画来谈谈如何实现他的动画过渡。 

1 玩家角色移动伴随的简单动画 

第一章就简单谈一谈,对于一个传统的RPG 2D小游戏,玩家操控的主角角色在游戏场景中会需要哪些动画。

1.1 行走

如果一个游戏视角是俯视的上帝视角,角色就只有向上、向下、向左、向右四个方向的行走空间,一般如果改变方向,直接瞬间切换。

还需要注意的一点是,既然行走有四个方向,那就决定了接下来的所有动作,四个方向都应该有不同的表现过程,因此一般动画片段每个状态都会由Left、Right、Up、Down四组组成。

1.2 停留

为了让细节感更足,很多游戏会把人物停止不动时喘气动作做出来,就会有起伏感。因此除了行走动画,还会有人物停止不动时的动画效果。

当然,停留动画对于四个不同的方向都需要有自己的动画片段。

1.3 攻击敌人(触发型)

除了基本的移动动画,一般角色还有发射炮弹、飞镖等等攻击时的动画效果,而且是在发射炮弹的瞬间触发的,例如下面这个向右发射的动作演示。

攻击动画与上述行走、停留动画不同的是,攻击动画属于触发型动画,由于攻击这个动作具有瞬时性,因此在角色脚本中一般以一个bool变量体现。

同样的,攻击也需要有四个方向不同的动画。

1.4 受伤(触发型)

一般RPG会有敌人和陷阱的设置,场景中如果角色触碰到敌人、受到敌人炮弹攻击、误入陷阱等,都会受到伤害,此时也需要一个受到伤害瞬间的动画效果。

与攻击动画相同,受伤也属于触发型动画,在角色脚本中一般以一个bool变量体现。

同样的,受伤也需要有四个方向不同的动画。

1.5 跳跃

对于一些2D横轴游戏,玩家角色一般会把移动分为左右行走、向上跳跃和下蹲的四种运动状态。

这里我认为跳跃是一种长久的状态,在角色从离开地板到落向地板的过程中都会维持一个跳跃的姿势。

1.6 下蹲

下蹲也是横轴游戏一个常见的动作状态,一般是长按某个键一直处于下蹲动作状态。 

2 动画间的过渡

游戏中不可避免会遇到处理动作过渡的情况,这也是Unity中Blend Tree混合树的最大的功能——通过某些参数处理动画的混合。

下面是我正在学习教程中角色混合树中动作片段之间的Transition关系:

其中:Moving、Idle、Hit、Launch分别表示移动(行走)、停留、受伤、攻击的动作,可见动作之间的混合情况是非常多的,例如:

  • 走着走着停下来
  • 停下来的时候受到攻击、受伤后停下来
  • 走着走着开始攻击敌人

我们需要梳理清楚,采用什么变量来进行两个动作间的过渡判断才合适呢?

3 过渡的判断逻辑

3.1 行走与停留:移动速度

这个很好解决,当移动速度大于0时就判断在行走,不移动时判断为停留。

3.2 受伤&攻击:bool变量

前面提到了受伤和攻击其实都是一个瞬时的东西,因此其实在判断是否过渡的时候用一个bool变量就可以跟其他动画相互跳转。

4 根据实例展示Blend Tree与脚本的协作

4.1 在状态机中创建BlendTree

创建了4个混合树并按需命名

4.2 创建连接:Make Transition

右键Make Transition创建混合树之间的联系。

4.3 创建所需变量并在Transition中加入逻辑

  • 在Animator窗口左侧的变量区,新建混合所需变量

由上面讨论的过渡的判断逻辑可知,本实例所需变量有:当前移动速度Speed、攻击和受伤的触发bool变量Hit和Launch。

同时,由于玩家角色做某种动作的时候还需要一个变量控制他面朝的方向,因此还需要一个Vector2类型的变量,这里分别创建一个Look X和Look Y,二者组成了二维变量(Look X, Look Y)

  • 还需要在混合树的属性栏添加变量控制的逻辑——Hit

Animator窗口中指向Hit的Transition,还需要调用上面创建的Trigger也就是bool类型的变量Hit,

点击箭头,进入Transition属性栏,在Conditions中加入Hit变量 

  •  在混合树的属性栏添加变量控制的逻辑——Idle

状态idle判断的条件是看Speed是否接近于0(由于浮点数没办法全等于0),因此可以设定某个限值,例如0.1,条件给Speed < 0.1即可,

 在混合树的属性栏添加变量控制的逻辑——Run

Run的判断条件是,Speed > 0.1

4.4 搭建每个混合树变量与Motion的关系

这里就是将每个混合树代表的动作合集,与其关联的动作片段,通过变量联系在一起。

例如停止状态idle,它包含四个不同方向idle的动作效果,因此需要通过(Look X, Look Y)这个二维变量的值来控制。

其他三个状态同理,都是基于(Look X, Look Y)这个二维变量的值来控制的。

4.5 脚本中加入玩家键盘控制与角色动作的逻辑关系

首先,玩家操作的角色和场景中不需要被操作的角色不同,还需要将不同状态的动画与玩家键盘输入的轴值关联在一起,才能实现动作与玩家移动角色同步。

项目中的玩家角色都会有一个专门控制其移动的脚本,例如实例项目中就有Ruby Controller这个脚本。

注意:以下出现的脚本代码只会展示当前涉及到的代码段,篇幅原因省略了其余的代码内容~

1 获取动画组件

与修改和操作其余任何组件一样,动画对于游戏对象来说也是由Animator组件控制的,因此在进行所有操作之前,需要先获取当前游戏对象的动画组件。

public class RubyController : MonoBehaviour

    Animator animator;
    
    private void Start()
       
        animator = GetComponent<Animator>();
    

2 定义变量

这里需要定义2个变量:

  • 一个获取当前角色移动时轴输入值的二维变量move
  • 一个用以储存移动时当前面朝向的二维变量lookDirection
public class RubyController : MonoBehaviour

    //当前移动使的轴输入
    Vector2 move;
    //移动时的面朝向,初始朝向右
    Vector2 lookDirection = new Vector2(1, 0);

3 Update()中定义当前变量与BlendTree变量相关联的逻辑

由于玩家操作轴是在Update()中完成的,因此需要在Update()里加入定义的变量move、look与BlendTree中的几个变量的逻辑关系。

public class RubyController : MonoBehaviour

    void Update()
    
        //确定静止时的面朝向
        //确定当前的移动的朝向,通过按键确定
        move = new Vector2(horizontal, vertical);
        //如果当前Ruby正在移动:
        //Approximately表示判断浮点数是否近似相等
        if (!Mathf.Approximately(move.x, 0.0f) || !Mathf.Approximately(move.y, 0.0f))
        
            //赋予移动时当下的朝向
            lookDirection.Set(move.x,move.y);
            //归一化
            //blend tree 中表示方向的参数范围是[-1,1],因此需要归一化
            lookDirection.Normalize();
        
        //动画
        //传递面朝方向
        animator.SetFloat("Look X", lookDirection.x);
        animator.SetFloat("Look Y", lookDirection.y);
        //传递矢量长度,作为速度
        animator.SetFloat("Speed", move.magnitude);
    

4 在脚本中关联bool变量Hit

当前没有涉及到攻击的设定,因此先不考虑角色攻击的效果,仅考虑受伤害时的动画。受伤混合树中定义的bool变量Hit控制玩家是否触发受伤动画。

脚本中,在减血的方法中添加下列语句

    //更改生命值
    //amount是游戏中加血/减血的操作
    public void ChangeHealth(int amount)
    
        if (amount < 0)//if >0加血,则不进入无敌时间
        
            //受伤的动画
            animator.SetTrigger("Hit");
        
    

5 效果展示

5 涉及到的Unity中C#用法

5.1 animator.SetTrigger/SetFloat

定义动画组件中的变量值,调用格式:

animator.SetTrigger(String)

animator.SetFloat(String, value)

5.2 .Set()

给某个Vector变量直接赋值

vector2.Set(x, y)

5.3 .magnitude

vector2.magnitude

返回一个浮点数,表示当前相对速度大小(保留大小丢失方向信息)

5.4 .Normalize()

vector2.Normalize()

将一个向量归一化操作,变成大小为1仅表示方向的单位向量(保留方向丢失大小信息)

5.5 Mathf.Approximately()

Mathf.Approximately(float, float)

浮点数中近似相等比较,由于浮点数有很多位小数点,如果直接用全等判断“==” 就永远不可能相等,这里相当于给判断多了一个Epsilon的误差值。

5.6 new

由于Vector2不能像方法一样使用,一般给一个Vector2类型的变量赋某个二维值的时候需要用到,例如:

Vector2 sample = new Vector2(1, 0)

Unity C#入门教程——动画时钟实现

参考技术A

显示当前时间的时钟

为游戏对象创建层级关系

编写脚本并与对象关联

使用命名空间

使用方法更新游戏物体

按时间进行旋转

在此教程中我们编写一个简单的C#脚本来制作时钟指针动画。

要求大家已经对Unity的编辑器有了基本的了解,其实,只需用过Unity几分钟就可以开始该案例了。

很快我们就能完成以下成果。

制作时钟

不用任何Unity资源包,我们从0开始创建Unity工程。缺省的场景中有一个位于 (0, 1, -10), 朝着z轴的负方向的摄像机,为了使摄像机中显示的透视图与场景一致,选择摄像机,并在菜单中选择执行 GameObject /* Align View*将摄像机与当前场景对齐。

啥是 游戏物体

子物体又是哈东东?

我们就简单用立方体来制作时钟的指针,为每个指针使用 GameObject/ Create Other / Cube 创建立方体。对于时针,设置其位置为 (0, 1, 0) ,三个轴上的缩放分别为 (0.5, 2, 0.5) .,对分针位置为 (0, 1.5, 0) ,缩放 (0.25, 3, 0.25) ,秒针的则分别是: (0, 2, 0)
**(0.1,4, 0.1)。
**

创建的时钟,以及其中游戏物体间的层级关系。

制作时钟指针动画

要让时钟动起来,就得写点脚本了。在工程视图中右键,选择 Create/ C# Script 新建一个C#脚本,将其命名为 ClockAnimator。 双击打开之,将其中内容清空,从空文件开始。

首先,我们要引用Unity的命名空间,接着就是定义 ClockAnimator 类。将其定义为一个公开的类,继承自[MonoBehaviour]

using UnityEngine;

public class ClockAnimator : [MonoBehaviour]

神马是命名空间?

类又是啥?

关于****[MonoBehaviour]****类?

这样我们就创建了一个可以作为组件的最小的类。保存之,接着从 Project 窗口中把它直接拖放到 Hierarchy (层级)视图的 Clock 游戏物体上,建立其与该游戏对象的关联。当然,也可以使用 Clock 游戏物体的 Add Component 按钮。

将ClockAnimator与Clock关联

要让指针动起来,我们得使用指针组件的 Transform 对象。首先,在刚才的脚本中为每个指针添加一个 Transform 变量,并保存它。这样,这些公开变量就成为可在编辑器中被赋值的组件属性,编辑器会获得这些游戏物体的 Transform 组件,并将它们赋予这些变量,选择 Clock ,将指针对应的游戏物体赋给这些属性。

变量是什么?

using UnityEngine;

public class ClockAnimator : [MonoBehaviour]

为空的ClockAnimator属性和填写属性后的ClockAnimator

下面在脚本中添加一个update方法。这是一个特殊的方法,它会在每一帧播放时调用,我们在这个方法中实现时钟指针的旋转。

using UnityEngine;

public class ClockAnimator : [MonoBehaviour]

方法是啥?

[ Update ] 方法是否应当公开?

保存脚本,编辑器会提示组件中已经有了update方法,并在脚本组件的左侧出现一个复选框,这样我们就能禁用该脚本组件了,当然此时,还是要保持它处于可用状态。

ClockAnimator更新的显示了复选框

每个小时,时针要转动360/12度;分钟指针则是每分钟转动360/60度;而秒针是每秒旋转360/60度。为了程序中使用方便,我们把这些值定义为私有的浮点常量。

using UnityEngine;

public class ClockAnimator : [MonoBehaviour]

常量有什么特殊性?

为了让时钟转动起来,每次update时,我们先得到当前系统的时间。System命名空间中的[DateTime] 结构体 可以用来存储时间,而该结构体中的静态属性Now可以返回当前时间,这样,每次update时,我们就先得到该值并将其存储到一个临时变量中。

using UnityEngine;

using System;

public class ClockAnimator : [MonoBehaviour]

什么是结构体?

属性又是什么?

要让指针转动,就需要更新指针的旋转,而这可以通过设置指针的localRotation实现。使用四元数:[Quaternion]可以定义任意角度的旋转。

因为摄像机朝向是z轴,Unity使用的是左手坐标系统,因此指针应该是绕着Z轴负方向进行旋转。

using UnityEngine;

using System;

public class ClockAnimator : [MonoBehaviour]

时间显示为12:44

四元数quaternion是什么?

旋转又是啥?

改进时钟的实现

很好!在游戏的运行模式中,时钟已经可以显示当前的时间了,但是使用离散的时间值让它看起来更像是一个电子钟。下面增加一个选项,实现模拟时间显示。在脚本中添加一个公开的布尔变量 analog ,用它来决定update方法中的显示方式,这样我们就能在编辑器中直接控制时钟的显示方式了,即使是在游戏运行时。

using UnityEngine;

using System;

public class ClockAnimator : [MonoBehaviour]

添加了analog模式的ClockAnimator

对于模拟现实显示的选项,我们使用和之前稍稍不同的方式。这次不用[DateTime].Now,我们用[DateTime].Now.TimeOfDay,这是一个时间段[TimeSpan]。返回的是自每天午夜开始到现在已经经过的小时,分钟和秒数。由于这个值是双精度数,使用时我们需要将它们转换为float类型。

类型转换的意思是

using UnityEngine;

using System;

public class ClockAnimator : [MonoBehaviour]

按照模拟方式显示的时钟
现在时钟也可以按模拟方式显示了。
unitypackage PDF
**
****原文链接:
** http://catlikecoding.com/unity/tutorials/clock/

以上是关于Unity入门计划Unity2D动画-脚本与混合树实现玩家角色动画过渡的主要内容,如果未能解决你的问题,请参考以下文章

Unity2d人物移动+动画控制

unity2d游戏入门开发【三】各个面板作用

unity实战:教你做黄豆君

unity实战:教你做黄豆君

unity实战:教你做黄豆君

unity实战:教你做黄豆君