【零基础入门unity游戏开发——动画篇】新动画Animator的使用 —— AnimatorController和Animator的使用

考虑到每个人基础可能不一样,且并不是所有人都有同时做2D、3D开发的需求,所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇

  • 【C#篇】:主要讲解C#的基础语法,包括变量、数据类型、运算符、流程控制、面向对象等,适合没有编程基础的同学入门。
  • 【unity通用篇】:主要讲解unity的基础通用的知识,包括unity界面、unity脚本、unity资源管理、unity动画、unity摄像机等,适合unity初学者入门。
  • 【unity3D篇】:主要讲解unity3D的知识,unity3D角色、unity3D物理系统、unity3D光照等,适合只想做2D游戏的开发者学习。
  • 【unity2D篇】unity2D篇:主要讲解unity2D的知识,包括unity2D角色、unity2D物理系统、unity2D光照等,适合只想做3D游戏的开发者学习。

这样方便大家按需选择性的去学习,比如有编程基础的大概率可以直接从unity通用篇开始入门,没有编程基础的建议从C#篇开始学习。只想做2D游戏的话,可以直接从unity2D篇开始学习,3D篇大概率就不需要看了,节约学习时间成本。

文章目录

前置知识

学习本章知识,得先去看看Animation动画相关知识:【零基础入门unity游戏开发——动画篇】Animation动画窗口,创建编辑动画

一、使用新动画Animator

方法一 自动关联动画

适合没有动画,想通过unity自定义创建编辑动画

1、打开动画窗口

在这里插入图片描述

2、创建Animation动画文件

在场景中选择需要创建动画的对象,在 Animation 窗口创建一个动画文件。
在这里插入图片描述
通过为场景中物体创建动画时会自动创建animator组件,并且关联 AnimatorController动画控制器文件。
在这里插入图片描述
双击AnimatorController动画控制器文件,打开 Animator 窗口可以看到刚刚添加的 Animation 文件已经添加到窗口中了。
在这里插入图片描述

方法二 手动创建关联动画

适合已有动画,为特定模型绑定对应动画

1、创建动画器控制器

在 Project 窗口右键创建动画器控制器
在这里插入图片描述

2、拖入动画

新建的 AnimatorController 文件是空的,可以拖 Animation 文件进去。双击动画器控制器,编辑动画控制器,拖入准备好的动画。
在这里插入图片描述

4、绑定控制器

新建cube,添加animator组件,拖入绑定动画控制器
在这里插入图片描述

二、Animator动画器组件参数

在这里插入图片描述

1、Controller 控制器

动画状态机控制器。我们需要在这里放置一个AnimatorController,也就是动画状态机控制器,它是我们组织并管理动画片段的工具,只有放置了animator controller才能播放动画

2、Avatar 绑定骨骼

如果我们要播放的是使用了avatar系统的人形动画,这里要注意一点,如果我们没有使用avatar,那么animator组件会严格按照动画片段里记录的path,去寻找相应的游戏对象并播放动画。

3、Apply Root Motion 应用根运动

是否启用动画位移。有些动画本身带位移,勾选Apply Root Motion,就会使用动画的位移。
在这里插入图片描述
如果我们希望通过自己编写脚本来控制角色的位移和旋转,那么这里就不用勾选。
UpdateMode 更新模式(一般不修改它)

4、Animate Physics 动画物理

通知物理系统动画变换。

5、Update Mode 更新模式

在这里插入图片描述
在这里插入图片描述

  • Normal:正常更新。update模式同步刷新
  • Fixed:物理更新。FixedUpdate模式同步刷新
  • Unscaled Time:不受时间缩放影响。这个unscaled time和normal一样都是与update的方法同步刷新,但是这个模式下会忽略当前的时间标尺time scale 。

如果修改time scale 会发现只有第三个模式动画不受影响
在这里插入图片描述

6、Culling Mode 剔除模式

所谓剔除原本是图形学上的一个概念,也就是指当某个物体并没有被摄像机看到时,那么我们就不需要去渲染它。那么同理在动画里就是指当这个游戏对象,没有被摄像机所看到时,那么我们应该做如何的处理。
在这里插入图片描述
在这里插入图片描述

  • Always Animate:始终播放动画,即使在屏幕外也不剔除。就是不进行剔除,不管摄像机有没有看到它,我们的动画不受影响。
  • Cull Update Transforms:摄像机没有渲染该物体时,停止位置、IK的写入。这是指如果该游戏对象并没有被摄像机看到,那么animator还是会计算当前的动画状态等到摄像机再次看到该物体时,你会发现这里和上面的always animate并没有什么区别,但是选择这个选项会剔除诸如IK之类的操作。
  • Cull Completely:摄像机没有渲染物体时,整个动画被完全禁用,等被看到时再重新播放动画。

下面的例子,播放动画时,如果我们旋转一圈摄像机,可以看到前两个的动作还是同步的,但最后一个已经明显不一样了,这说明刚才摄像机没有看到它的时候,它的动画组件实际上是被禁用了的
在这里插入图片描述
我们再来看一下有IK的情况,比如下面头部IK一直看向这个球,当我们摄像机不看他们时,会发现第二和第三的头部都不会转动了
在这里插入图片描述

三、AnimatorController面板参数

在这里插入图片描述

1、Layers 图层

动画层级页签,为动画添加更多的层级,层级权重高的动画播放会覆盖层级低的。
在这里插入图片描述

  • 可以点击加号添加层级。
  • 点击层级的设置按钮对层级进行设置,实战参考:动画混合

2、Parameters 参数

参数页签,为动画状态机添加控制状态切换的参数。点击加号添加四种参数变量条件。
在这里插入图片描述

3、网格化布局区域

主要用于编辑状态之间的切换关系。窗口中的每一个矩形表示一个状态,每一个箭头表示一个切换条件。
在这里插入图片描述

3.1 系统自带的默认动作

每个图层有三个默认状态
在这里插入图片描述

状态 解释 介绍
Any State 任何状态 从他创建的过渡连接到新动画,给个条件,无论处于当前场景里的什么状态,只要满足条件,都可以过渡为相连的新动画(比如人物站立跑步动画,正常游戏应该是所有的动画最终都可以切换到站立跑步动画,如果不靠Any State,那么一个动画就需要连一次站立跑步动画,100个动画就得连100次,工作量可想而知)
Entry 入口状态 进入状态机流程。角色开始的默认状态
Exit 出口状态 退出状态机流程。这个用于子状态机的使用,这个我们一般很少用它。

3.2 自定义的动作

在这里插入图片描述

  • 橙色矩形:一开始的默认状态动画,和 Entry 相连,表示一开始播放的动画。
  • 灰色矩形:自己添加的某一种动作状态。

注意:Animator 窗口的动画矩形的名字可以自由定义,他已经关联了 Animation 动画文件,默认会和动画文件的名字一样,可以自行修改。
在这里插入图片描述

四、动画状态的基本属性

在这里插入图片描述

1、Tag 标签

通过打标签,我们可以给不同的动画状态进行分类,以便于我们通过代码进行管理。

比如

//获取状态机
var animator = GetComponent<Animator>();

//获取状态机的当前状态,参数为层级序号,0表示BaseLayer
AnimatorStateInfo stateInfo=animator.GetCurrentAnimatorStateInfo(0);
//也可以这样写,注意这个stateInfo每一帧都在更新
// AnimatorStateInfo stateInfo=animator.GetCurrentAnimatorStateInfo(animator.GEtLayerINdex("Base Layer"));

//判断当前状态机的状态的tag是否是tagName
bool flag = stateInfo.IsTag("tagName");

2、Motion

该状态所管理的动画片段。如果这个状态是由混合数BlendTree建立的话,那么这里放的就是它所管理的那颗混合树。

3、speed 速度

动画的播放速度。1是正常速度,超过1就是加速,小于1就是减速,如果是负值就是倒放
在这里插入图片描述
这个Speed属性是不可以通过脚本更改的,如果我们需要修改游戏中的动画播放速度的话,就需要集合下面这个属性Multiplier,动画的实际播放速度将会是Speed与Multiplier的乘积,我们需要选择一个关联Multiplier的浮点的新变量。

如图只需要我们在脚本里更改animSpeed的大小就可以更改动画播放的速度
在这里插入图片描述

//设置动画的播放速度
animator.SetFloat("animSpeed",1);
int speedHash=Animator.StringToHash("animSpeed");
//这行代码与第一行效果一致
animator.SetFloat(speedHash,1);

4、Motion Time

播放动画片段定在一个特定时间点。它也需要关联一个float参数,新建一个变量Process

如果我们给Process的值为0.5,那么这个状态就会一直播放在它所管理的那个动画片段的最中间的那一帧,并且定在那一帧就不动了。如果为0那么状态机就会播放这个动画片段的第一帧也定在那里不动
在这里插入图片描述

5、Mirror 镜像

镜像动画。只对人形动画有用
在这里插入图片描述

6、CycleOffset

动画偏移。比如0.5就是从动画中间开始播放。

7、Foot IK

它是一种使用了IK的动画校正机制,比如当我们把骨骼系统转化为肌肉系统之后,人形角色的双手和双脚的位置会出现一定的偏移,unity为了解决这个问题,提前为我们保存了骨骼系统下手和脚的正确位置,并把这些位置放置在了四个IK Goal上,把我们脚部的实际位置向这里的IK Goal的位置拉近一点

我们把它勾上看一下
在这里插入图片描述
这里有两点需要注意

  • 首先,Foot IK只是略微的调整脚部的位置,它可以在一定程度上改善脚部动画的不自然,但是不一定能够满足高质量的动画需求。
  • 其次,我们调整IK Goall的位置并不会更改Foot IK的效果,Foot IK所参照的其实并不是这个IK Goalf的本体,而是这个IK Goal当前的或者说初始的位置

8、Write Defaults

从A到B动画的过渡,如果B的动画曲线不包含Scale属性,如果没有勾选WriteDefault,会集成A动画的Scale属性。
在这里插入图片描述
如图A动画将cube的scale修改为(3,3,1),如果B状态的属性没有勾选WriteDefault,那么cube在执行B动画时会以scale为(3,3,1)的数值做平移动画,也就是说会继承A播放完成时的动画属性,注意仅限B动画没有Scale变化的动画曲线。如果勾选了WriteDefault,那么cube在执行B动画时scale是(1,1,1),不会继承前动画属性,而是使用一个默认值

那么Unity是在什么时候设置的这个默认值呢?
是在Animator组件调用OnEnable方法时,获取Cube的Scale作为默认值,也就是说Cube的enable属性被反复勾选时,Animator会多次读取cube的状态作为默认值。

这可能就会出现一个问题,如果cube在scale为(2,2,2)时setActive(false),然后setActive(true)后,scale的默认值会变成(2,2,2),下次在播放b动画时,会以(2,2,2)的属性做平移(B勾选了WriteDefault的前提)。

所以如果动画出现莫名其妙的bug,试试查看是不是WriteDefault导致的。

五、状态切换连线

1、自定义关联动画

我们可以在面板右键创建状态,再关联动画。
在这里插入图片描述
在这里插入图片描述

2、切换默认播放动画

游戏一运行会直接播放默认状态连线的动画,我们可以手动进行切换。
在这里插入图片描述
效果
在这里插入图片描述

3、创建过渡

对一个矩形右键选择创建过渡。
在这里插入图片描述

创建后会出现连线,选择另一个矩形进行连接。点击连接线可以看到右侧多了很多参数。
在这里插入图片描述

添加连线后意味着这两个矩形状态可以进行状态切换,可以给连线设置切换的条件。没有连线的话两个状态不能进行切换。

4、添加状态切换条件

把左侧面板切换成参数标签,
在这里插入图片描述

5、设置动画间切换条件

选择一个连线,点击下方条件列表添加切换条件,点击下拉框会出现我们刚刚设置好的切换条件参数进行选择。同理选择条件框后按减号可以删除。
在这里插入图片描述
注意:连线上的这些条件要同时满足才能完成状态的切换。

  • Float: 一个带有小数部分的数,可以选择大于或者小于和后面设置好的数比较判断是否满足条件。
    在这里插入图片描述

  • Int:一个整数,可以选择大于,小于,等于,不等于和后面设置好的数比较判断是否满足条件。
    在这里插入图片描述

  • Bool:真或假的值(用复选框表示),和设置好的真假进行比较判断是否满足条件。
    在这里插入图片描述

  • Trigger:一个布尔参数,当被转换消耗时,由控制器重置(用圆形按钮表示)。可以理解为特殊的 bool 值,当设置为 true 完成切换条件后马上会自动设置为 false。
    在这里插入图片描述

六、状态切换连线参数

在这里插入图片描述

1、HasExitTime(是否有退出时间) 和 ExitTime(退出时间)

如果勾选HasExitTime,当切换动画时,动画一定是播放到下方的Exit Time(百分比)的时间时才过渡到下一个动画,没什么特殊需求的话,想立刻切动画,就不勾选这个选项。
在这里插入图片描述
当勾选上方的Has Exit Time时,ExitTime值决定了过渡生效的确切时间。该值可以大于1,如果小于1,比如0.85,表示当动画播放到了85%的动画时,就会过渡。如果大于1,比如4.5,那么动画将循环4.5次后过渡到下一个动画。

3、FixedDuration(固定持续时间) 和 TrnaitionDuration 过渡持续时间

选中后,下方的TrnaitionDuration过渡持续时间将以秒为单位解读过渡时间,如果不选中,则以百分比解读过渡时间。
在这里插入图片描述
TrnaitionDuration 相当于从该状态切换到下一状态的过渡动画持续的时间,对应下方两个蓝色箭头包裹区域。
在这里插入图片描述

4、Transition Offset 过渡偏移

过渡到目标状态的起始播放的时间偏移。如果是0则从要切换到的目标状态开头开始播放,如果是0.5则从要切换到的目标状态的一半开始播放,你可以理解为切入下一个状态的切入点。
在这里插入图片描述

5、Interruption Source 中断源

该过渡中断的情况。
在这里插入图片描述

  • None:不在添加任何过渡
  • Current State:将当前状态过渡排队
  • Next State:使下一个状态的过渡进行排队
  • Current State Then Next State:将当前状态的过渡和下一个状态的过渡都依次排队
  • Next State Thne Current State:将下一状态的过渡和当前状态的过渡依次排队

6、Ordered Interruption 有序中断

当前过渡是否可在不考虑顺序的情况下被其它过渡中断

  • 选中时,找到有效过渡或当前过渡时,会中断
  • 不选中时,找到有效过渡,会中断

7、Conditions:过渡条件

如果没有过渡条件,只会考虑Exit Time

8、AnyState和动作之间连线参数

如果是AnyState和动作之间连线的话会多出两个参数
在这里插入图片描述

8.1 Can Transition To self 可以过渡到自己

是否可以过渡到自己,一般取消勾选

8.2 Preview source state

预览各种过渡状态,可以查看从任意状态切换到当前状态的过渡效果
在这里插入图片描述

七、Animator动画器代码控制

1、获得Animator组件

animator = this.GetComponent<Animator>();

2、通过状态机条件切换动画

Animator.SetXXX方法

我们用代码控制状态机切换主要使用的就是Animator提供给我们的API,我们知道一共有四种切换条件 int float bool trigger,所以对应的API也有4种。

//设置动画参数状态
animator.SetFloat("条件名", 1.2f);
animator.SetInteger("条件名", 5);
animator.SetBool("条件名", true);
animator.SetTrigger("条件名");

哈希处理字符串重要

使用哈希的主要原因是提高效率。状态机中的标签和参数通常用字符串表示,但字符串比较在性能上可能较慢。通过使用哈希值,可以将字符串转换为唯一的整数值,进行更快速的比较操作。这避免了每帧都进行昂贵的字符串比较操作,从而提升了状态机查询的性能。

比如

# 普通切换动画状态
anim.SetTrigger("attack");

# 对字符串进行哈希处理
private int _attackTrigger = Animator.StringToHash("attack");
anim.SetTrigger(_attackTrigger);

注意:字符串先转哈希值,再使用,这是一个好习惯,希望实际项目中大家能多多应用。

3、获得动画参数状态

Animator.GetXXX方法

//获得动画参数状态
animator.GetFloat("条件名");
animator.GetInteger("条件名");
animator.GetBool("条件名");

4、直接切换动画

除非特殊情况,不然一般不使用。

注意:状态名和动画名不一定一样。动画名拖进来默认名字就是状态名,但是可以修改。

//直接切换动画 
animator.Play("状态名");

八、Animator本质上是一个有限状态机

Unity 的 Animator是一个典型的有限状态机实现,因为它严格遵循 FSM 的核心定义,Animator本质上是把动画逻辑用状态机的形式可视化呈现,完美符合FSM的核心特征。

1、有限状态机(FSM)核心概念

  • 有限状态:系统拥有明确且数量有限的状态集合(如待机、移动、攻击)。
  • 状态转换规则:通过条件(如按键输入、时间阈值)触发状态切换。
  • 单一活跃状态:同一时间只能处于一个状态。

比如

假设你有一个智能台灯,它有3种状态:关闭、弱光、强光。

  • 状态:3种明确的模式(关闭/弱光/强光)

  • 转换条件:单击开关切到弱光,再单击切到强光,长按2秒关闭

  • 规则:任何时候只能处于其中一种状态

2、为什么Unity的Animator是FSM?

  • 状态集合:比如游戏中角色有站立、奔跑、跳跃、攻击等明确的动画状态

  • 转换箭头:Animator窗口中那些连接状态的箭头就是状态转换条件

  • 触发机制:通过设置参数(如"Speed>1"或"按下空格键")控制状态切换

  • 单一状态:角色同一时间只能播放一个基础动画(比如不能同时处于站立和跳跃状态)

九、实战

1、实现角色播放说话动画

1.1 导入动画人物资源

前往unity资源商城购买免费资源,下载导入

拖入角色
在这里插入图片描述
预览动画
在这里插入图片描述

1.2 给人物绑定默认动画

注意,这里我们想学习动画的使用,所以我们就不用资源自带的动画器控制器了,新建ManController控制器
在这里插入图片描述
拖入绑定控制器
在这里插入图片描述

编辑控制器
在这里插入图片描述

1.3 绑定两个动画切换

拖入新的动画,说话动画
在这里插入图片描述
创建过渡,连接两个动画
在这里插入图片描述
运行查看效果,站立动画执行完就会执行说话动画(只会执行一次说话动画)
在这里插入图片描述

1.4 循环播放两个动作

再创建一条过渡,当说话动作执行完,又会执行站立,实现无限循环
在这里插入图片描述

1.5 参数控制动作的切换

实现参数按钮控制动画过渡,添加Trigger(触发器)
在这里插入图片描述
过渡绑定条件参数,选择F,当F被触发时才会过渡为说话动画
在这里插入图片描述
点击F参数,触发一次说话动作
在这里插入图片描述

1.6 写脚本控制动作的切换

写脚本控制F参数的触发

void Update()
{
    
    
     //按下一次键盘F按钮,触发一次参数F事件
     if(Input.GetKeyDown(KeyCode.F)){
    
    
         GetComponent<Animator>().SetTrigger("F");
     }
 }

1.7 动画切换延迟问题

实操过程中,你会发现动作切换有延迟,原因是每个动作都有他的读条时间,一个动作读条结束才会执行下一个动作
在这里插入图片描述
如何解决延迟问题?取消勾选过渡动画的退出时间即可
在这里插入图片描述
最终效果,动作切换非常的丝滑
在这里插入图片描述

2、实现角色从站立到跑步动画的来回切换

2.1 配置动画控制器

拖入角色站立和跑步动画
在这里插入图片描述
因为跑步是持续性的,和前面说话动画不一样,所以应该使用前面的三个参数控制都可以,我这里用的bool值,修改参数名为isRun
在这里插入图片描述
绑定过渡条件,isRun=true切换为奔跑状态,isRun为false变为站立状态
在这里插入图片描述

在这里插入图片描述
记得去掉两个过渡条件退出时间的勾选,不然动作切换会有延迟
在这里插入图片描述

2.2 编写代码控制人物

代码实现按键控制人物朝向,移动和播放不同动作

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

public class ManScript : MonoBehaviour
{
    
    
    private Animator animator;
    // Start is called before the first frame update
    void Start()
    {
    
    
        animator = GetComponent<Animator>();
    }

    // Update is called once per frame
    void Update()
    {
    
    
        //水平轴
        float horizontal = Input.GetAxis("Horizontal");
        //垂直轴
        float vertical = Input.GetAxis("Vertical");
        //向量
        Vector3 dir = new Vector3(horizontal, 0,vertical);
        
        //当用户按下方向按键
        if(dir != Vector3.zero){
    
    
            //人物一直面向向量
            transform.rotation = Quaternion.LookRotation(dir);
            //播放跑步动画
            animator.SetBool("isRun", true);
            //如果动画不带移动效果,还得控制人物进行移动(我这里动画有移动效果所以不需要),因为人物一直面向向量,所以直接控制人物朝前方行走即可
            //transform.Translate(Vector3.forward*2*Time.deltaTime);//每秒朝前方移动2米
        }else{
    
    
            //播放站立动画
            animator.SetBool("isRun", false);
        }
    }
}

2.3 结果

在这里插入图片描述

2.4 过渡时间

如果你实际操作,会感觉稍微有一点不跟手,因为动作过渡默认会设置一个过渡时间,如果你不想要可以把它设置为0(注意:没有过渡时间可能导致动作切换有点生硬,所以具体还是看自己的选择)
在这里插入图片描述


专栏推荐

地址
【零基础入门unity游戏开发——C#篇】
【零基础入门unity游戏开发——unity通用篇】
【零基础入门unity游戏开发——unity3D篇】
【零基础入门unity游戏开发——unity2D篇】
【制作100个Unity游戏】
【推荐100个unity插件】
【实现100个unity特效】
【unity框架/工具集开发】

完结

好了,我是向宇,博客地址:https://xiangyu.blog.csdn.net,如果学习过程中遇到任何问题,也欢迎你评论私信找我。

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_36303853/article/details/145149261
今日推荐