第三十三章 Unity Mecanim动画系统(下)

news2024/11/21 0:35:28

本章节,我们继续讲解Unity的 Mecannim 动画系统。在上一章节中,我们设置了动画过渡,但是还没有为这些动画过渡设置过渡条件。这个过渡条件需要在“Animator”窗口中设置。这个窗口的左边是用来编辑“动画层”和“动画参数”的。这里的“动画参数”就是我们所指的“过渡条件”,也就是说这个条件是通过“动画参数”来实现的,我们先点击“Parameters”,看看它的样子,如下所示:

这是一个参数列表,目前是空的,我们需要点击右上角的“+”来添加参数。

我们点击之后,会有一个弹框,看名字能猜出来,这就是四种数据类型。Float是小数类型,Int是整数类型,Bool是布尔类型,Trigger是触发类型(也可以理解为布尔类型)。那我们选择哪一种呢?我们先选择第一个Float小数类型试试吧。

我们给这参数变量重新命名为“walk_run”,它的默认值是0。有了这个“walk_run”的过渡条件(动画参数)后,该如何设置过渡呢?我们点击idle2到walk2的过渡线(蓝色显示),然后查看Inpector检视视图,

两个状态机(idle2和walk2)的切换默认是动画播放完毕,也就是ExitTime。但是这个时间是可以修改的。也就是说,当动画A切换到动画B的时候,我们可以控制动画A播放到那个进度的时候切换到动画B,不用等到动画A完全播放完毕再切换到动画B。这个控制可以在检视面板中清楚的可视化修改。也就是ExitTime后的数值。当然我们有时候,也希望idle2和walk2可以随时切换,而不是必须等待播放ExitTime时间。此时我们就需要取消HasExitTime勾选项。也就是说,默认情况下是,播放完一个动画之后才能切换另一个动画。但是如果我们去掉HasExitTime选项后,可以随时打断当前动画立即执行下一个动画。我们举一个例子,大家就明白了。假如存在Run(跑步动画)到Attack(攻击动画)的动画过渡,一般情况下是,播放完Run之后才播放Attact。但是这种设定显然不太合理。玩家发送攻击后,就应该立刻攻击的,不应该等Run动画播放完毕才执行攻击动画。因此,我们就需要去掉HasExitTime选项。而Attack到Run的动画过渡,则应该勾选HasExitTime选项。因为必须攻击动作全部完成,才能切换到Run状态。我们不可能攻击动画执行一半就切换到Run状态,这个是不合理的。没有那个玩家攻击动作完成一半的时候,就切换到Run状态。

动画过渡检视面板中时间帧中,两个动画片段之间有重叠,其实是为了让两个片段有一个淡入淡出的过渡效果,而不是硬生生的从一个动画突然变成另一个动画。重合部分就是淡入淡出的效果。当然,我们可以手动拖动,改变这个淡入淡出的范围。

在上面截图中,我们主要关注一个“Conditons”项目的设置,它是一个列表,可以通过右下角的加减号来进行编辑,我点击“+”号试试。

点击完毕后,我们就明白了,这里就是选择我们刚刚添加的“动画参数”变量的。同时,我们还可以在这里对“动画参数”变量进行逻辑判断。例如,我们可以设置“walk_run”等于“1.0”的时候,使得我们当前的idle2到walk2的过渡生效,也就是从idle2动画切换到walk2动画。如何设置呢?在上面的新增加的条件中,有三个项目可以设置,第一个就是“动画参数”变量的选择,我们默认“walk_run”即可;第二个是操作符,我们也默认“Greater”(大于)即可;第三个就是操作值,我们也默认0即可。这三个设置就表示当“walk_run”变量值大于0(例如数值1)的时候,就可以从idle2动画切换播放walk2动画了。

接下来,我们在点击idle2到run2的过渡线(蓝色显示),然后在Inpector检视视图中设置条件,

这里我们设置的操作符是Less,也就是小于的意思,也就是说当“walk_run”变量值小于0(例如数值-1)的时候,就可以从idle2动画切换播放run2动画了。到目前为止,我们已经设置完了“过渡”以及“过渡条件”,关于这里的“Conditons”,我们再补充一点。我们可以添加多个“动画参数”变量共同完成这个过渡条件,这些变量直接是逻辑且的连接关系哦。

接下来,我们创建一个“GenericAnimationScript.cs”的脚本文件。然后使用代码来控制“walk_run”变量值来进行动画片段的切换播放了。

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

public class GenericAnimationScript : MonoBehaviour
{
    // 新版动画播放组件
    private Animator animator;

    // Start is called before the first frame update
    void Start()
    {
        // 获取Animator组件
        animator = GetComponent<Animator>();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            animator.SetFloat("walk_run", 1);
        }
        if (Input.GetKeyDown(KeyCode.S))
        {
            animator.SetFloat("walk_run", -1);
        }
    }
}

代码非常简单,我们同样需要获取Animator组件,然后使用它的方法来设置“动画参数”变量值。因为我们的变量是Float类型的,因此使用SetFloat方法。如果我们是Int类型的,就需要使用SetInt方法,依次类推。接下来,将脚本挂载到游戏对象Elf上,并运行工程。

当我们按下A键的时候,就完成了idle2到walk2的动画过渡,我们的模型就会循环播放walk2的动画。如果此时我们按下S键,它是不会播放run2动画的。这是为什么呢?因为我们按下S键的作用是从idle2到run2的过渡,而不是walk2到run2的过渡。那么,问题又来了,我们得添加walk2到run2的过滤线,并为此过渡线添加过渡条件(动画参数)。而且,我们还得需要设置walk2到idle2的过渡,因为角色一定存在走路(walk2)完毕后,进入休闲(idle2)状态的时候。这样的话,我们的“动画控制器”中,就可能形成一个网状结构,每一个“动画状态机”之间来来回回的建立过渡线,并且还需要为每一条过渡线设置条件。但是,好在这个过程是可视化的,我们只需要拖拖拽拽就完成了,不需要通过代码来完成。

接下来,我们再来说一说动画播放的其他内容。如何获取当前播放的动画信息。我们可以通过Animator组件来获取AnimatorStateInfo对象,该对象包含了动画状态(动画片段)的所有信息。代码如下:

        if (Input.GetKeyDown(KeyCode.A))
        {
            animator.SetFloat("walk_run", 1);

            AnimatorStateInfo current = animator.GetCurrentAnimatorStateInfo(0);
            bool isWalk = current.IsName("walk2");
            if(isWalk) Debug.Log("walk2");
        }

运行结果如下

代码animator.GetCurrentAnimatorStateInfo(0); 方法的参数就是动画层的索引,从0开始,默认层的索引就是0。如果添加了新的层,则索引就依次加1。current.IsName("walk2"); 判断当前播放的动画是不是walk2动画,walk2就是行走动画片段名称。另外,AnimatorStateInfo对象还有一个speed只读属性,用来表示动画播放的速度,默认值为1,表示正常播放。因为它是只读属性,因此,我们不能通过它来改变动画播放速度。我们可以通过Animator的speed属性来控制动画播放速度。同样,1 为正常播放速度。如果我们设置大于1的话,动画会加速播放,小于1的话,会减慢播放。如果是0的话,会停止播放。如果-1的话,会倒序播放。例如,我们想要动画播放速度增加1倍,可以这样设置:

animator.speed = 2.0f;

最后,我们来对比一些新旧两套动画系统的区别。就的动画系统使用的是Animation组件,新的动作系统使用的是Animator组件。这是第一个大的区别。其次,旧的动画系统比较简单,只是在Animation组件中设置所有的动画片段即可,然后由代码来控制各个动画片段的切换逻辑。而新的动画系统则是将这个“代码切换逻辑”放到了“动画控制器”中完成,并且提供了Animator窗口来进行可视化的编辑。在Animator窗口中,我们可以编辑所有动画片段之间的过渡以及过渡条件,这个过渡条件也比较多简单,基本的就是通过“动画参数”变量来实现的。很明显,这种设计取代了我们之前的“纯代码”的控制方式,使用图形化来展示各个动画片段是如何切换过渡的。虽然,这种设计并不能大量减轻研发人员的工作,但是这种清晰可见的设计方式,却可以帮助我们梳理切换逻辑,最大程度的减少出错的几率。

本课程涉及的内容已经共享到百度网盘:https://pan.baidu.com/s/1e1jClK3MnN66GlxBmqoJWA?pwd=b2id

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/491610.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis的20种使用场景

本文介绍Redis除了缓存以外的使用场景。 测试源码&#xff1a;https://github.com/vehang/ehang-spring-boot/tree/main/spring-boot-011-redis 1缓存 本文假定你已经了解过Redis&#xff0c;并知晓Redis最基础的一些使用&#xff0c;如果你对Redis的基础API还不了解&#xff…

Kubernetes服务搭建[配置-部署](Kubeadm)

文章目录 **[1 — 7] ** [ 配置K8S主从集群前置准备操作 ]一&#xff1a;主节点操作 查看主机域名->编辑域名1.1 编辑HOST 从节点也做相应操作1.2 从节点操作 查看从节点102域名->编辑域名1.3 从节点操作 查看从节点103域名->编辑域名 二&#xff1a;安装自动填充&…

Android - 动画

一、概念 补间动画 ViewAnimation&#xff08;Tween&#xff09;&#xff1a;不改变view的位置和属性。属性动画PeopertyAnimation&#xff1a;view的属性根据执行的动画发生真实的改变。帧动画 DrawableAnimation&#xff08;Frame&#xff09;&#xff1a; 二、补间动画 Vi…

SPSS如何进行使用时间序列模型之案例实训?

文章目录 0.引言1.时间序列数据平稳处理2.指数平滑法建模3.ARIMA建模4.季节性分解 0.引言 因科研等多场景需要进行绘图处理&#xff0c;笔者对SPSS进行了学习&#xff0c;本文通过《SPSS统计分析从入门到精通》及其配套素材结合网上相关资料进行学习笔记总结&#xff0c;本文对…

MYSQL用户组管理

1&#xff1a;使用明文密码创建用户 使用密文密码创建用户 1.2 查看用户信息 1.3 重命名用户 rename 1.4 删除用户信息 drop 1.5 修改当前登录用户的密码 set password password(123456); 1.6 修改其他用户的密码 set password for nancylocalhost password(abc123); 1.7…

2023年常见的20道JavaScript面试题及其答案解析,你知道多少

JavaScript中typeof操作符有哪些返回值&#xff1f; 答案&#xff1a;typeof操作符返回字符串数据类型。可能的返回值有&#xff1a;“undefined”、“boolean”、“number”、“string”、“object"和"function”。如何检查一个变量是否为数组&#xff1f; 答案&…

【JavaEE】Thread类

目录 前言 1、创建一个线程 1.1、 体会多线程的执行 1.2、体会单线程的执行 1.3、sleep方法&#xff08;休眠&#xff09; 1.4、通过第三方程序来观察线程详情 1.5、创建线程的方式 1.5.1、继承Thread类&#xff0c;重写run方法来创建线程 1.5.2、实现Runnable接口&am…

linux 查看系统版本

文章目录 一、查看Linux内核版本的命令二、查看Linux系统发行版本的命令三、 延伸&#xff1a; 一、查看Linux内核版本的命令 cat /proc/version 此命令可以查看正在运行的内核版本信息。/proc 目录存储的是当前内核运行状态的一系列特殊文件&#xff0c;包括&#xff1a;内存…

electron源码保护

electron 程序发布后&#xff0c;如果未对程序做保护&#xff0c;则极容易受到破坏&#xff0c;比如被轻松破解密码&#xff0c;或者被修改程序&#xff0c;所以必须对程序做一些安全防护。虽然没有100%的安全防护&#xff0c;但是提升破解难度&#xff0c;直至破解代价超出了范…

UML图中的domain model,object model,system sequence diagram以及interaction diagram

UML图&#xff08;Unified Modeling Language&#xff0c;统一建模语言&#xff09;是一种用于描述、可视化、构建和记录软件系统的标准化建模语言。在UML中&#xff0c;有很多类型的图&#xff0c;其中包括领域模型&#xff08;Domain Model&#xff09;、对象模型&#xff08…

拥抱智能时代:初探RFID系统

在数字化时代&#xff0c;人们越来越追求高效率和高质量的体验&#xff0c;以获得更快乐、更好的生活。RFID系统作为一项智能化管理技术&#xff0c;正越来越广泛地应用于各个领域&#xff0c;以提高效率和质量。本文将介绍RFID系统的基本概念、工作原理和实际应用案例&#xf…

OpenAI的编程语言和框架,给程序员带来了帮助有哪些

OpenAI 是一个人工智能开发公司&#xff0c;成立于2015年&#xff0c;总部位于美国旧金山。这家公司致力于研究和开发先进的人工智能技术&#xff0c;旨在将这些技术应用到解决全球一些最棘手的问题上。 OpenAI 以其卓越的技术和实验室出品的 groundbreaking AI papers 而闻名…

Android焦点流程梳理

作者&#xff1a;Cy13er 前言 最近在看一些焦点处理的问题&#xff0c;认真处理起来发现不跟着源码自己走一遍焦点相关的流程&#xff0c;对于问题的分析上会比较困难。所以本文主要对焦点流程进行一次梳理&#xff0c;在处理类似问题时也可以作为手册阅读。 起源 一切都要从…

Apache Kafka 进阶(一)

官网 Apache Kafka是一个开源的分布式事件流平台&#xff0c;被数千家公司用于高性能数据管道、流分析、数据集成和关键任务应用。 核心能力 高吞吐量 在网络有限的吞吐量下&#xff0c;使用延迟低至2ms的机器集群交付消息。可扩展性 将生产集群扩展到1000个代理&#xff0c…

SQLite安装配置

1.什么是 SQLite&#xff1f; SQLite是一个软件库&#xff0c;实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite是一个增长最快的数据库引擎&#xff0c;这是在普及方面的增长&#xff0c;与它的尺寸大小无关。SQLite源代码不受版权限制。 SQLite是…

Linux 五种网络IO模式(阻塞IO、非阻塞IO、IO多路复用、信号驱动IO、异步IO)

Linux网络编程中&#xff0c;有五种网络IO模式&#xff0c;分别是阻塞IO、非阻塞IO、IO多路复用、信号驱动IO、异步IO&#xff1b; 虽然说不能全都认识得很透彻&#xff0c;但至少得都知道一点&#xff01; 开始之前&#xff0c;先了解以下同步IO和异步IO&#xff1b; 1. 同步…

探索AIGC创新实践,亚马逊云科技与全球咨询合作伙伴携手同行

AIGC(AI Generated Content&#xff0c;人工智能生成内容)&#xff0c;已经成为全球出圈的科技热点。各行各业都在重新审视和思考AIGC的创新价值、未来趋势和成功实践&#xff0c;力争在这波热潮下寻找更多创新的可能性&#xff0c;重塑行业格局。 在AIGC领域&#xff0c;亚马…

无代码资讯|ChatGPT新功能曝光;Mendix与亚马逊云科技底层融合;无代码开发平台Appy Pie推出内置AI

栏目导读&#xff1a;无代码资讯栏目从全球视角出发&#xff0c;带您了解无代码相关最新资讯。 Top3大事件 1、ChatGPT 新功能曝光&#xff0c;GPT-4 迎来 AGI 历史性时刻&#xff01; 北美时间4月20日&#xff0c;Open AI联合创始人Greg Brockman受邀出席 “2023TED” 大会&…

手写【深拷贝】

JS中深拷贝的实现 JSON.parse(JSON.stringify())递归实现深拷贝 使用JSON.parse(JSON.stringify()) 实现 无法拷贝 函数、正则、时间格式、原型上的属性和方法等 递归实现深拷贝 es5实现深拷贝 源对象 const obj {name: 张桑,age: 18,hobby: [{name: 篮球,year: 5,loveSta…

极简爬虫通用模板

网络爬虫的一般步骤如下&#xff1a; 1、确定爬取目标&#xff1a;确定需要爬取的数据类型和来源网站。 2、制定爬取策略&#xff1a;确定爬取哪些网页、如何爬取和频率等。 3、构建爬虫程序&#xff1a;使用编程语言&#xff08;如Python&#xff09;实现爬虫程序&#xff…