【Unity3D小技巧】Unity3D中判断Animation以及Animator动画播放结束,以及动画播放结束之后执行函数
推荐阅读
- CSDN主页
- GitHub开源地址
- Unity3D插件分享
- 简书地址
- 我的个人博客
大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。
一、前言
在日常开发中,可能会遇到要判断Animation或者Animator动画播放是否结束的情况。
判断Animation是否结束可以这么写:
using System;
using System.Collections;
using UnityEngine;public class AnimationPlayControl : MonoBehaviour
{Animation ani;void Update(){AnimationState state = ani["Open"];if (state.normalizedTime >= 1) {// 判断动画播放结束normalizedTime的值为0~1,0为开始,1为结束。Debug.Log("动画播放完毕");}}
}
或者简单一点:
using System;
using System.Collections;
using UnityEngine;public class AnimationPlayControl : MonoBehaviour
{Animation ani;void Start(){if(!ani.isPlaying){Debug.Log("没有播放动画,或播放结束动画");}}
}
判断Animator是否结束可以这么写:
using System;
using System.Collections;
using UnityEngine;public class AnimationPlayControl : MonoBehaviour
{Animator anir;void Start(){//获取动画层 0 指Base Layer.AnimatorStateInfo stateinfo = anir.GetCurrentAnimatorStateInfo(0);//判断是否正在播放walk动画.if (!stateinfo.IsName("Base Layer.walk")){Debug.Log("没有播放walk动画,或播放结束动画");}}
}
但是,如果说要判断动画结束之后再执行某些事件就有些麻烦,首先需要在Update里面一直判断是否播放完,播放完再去执行事件。
消耗性能,也不好管理,所以就写了一个迭代器也就是协程来判断动画是否结束,结束后执行回调函数。
二、Animation动画播放结束判断
2-1、第一种协程写法
代码参考:
using System;
using System.Collections;
using UnityEngine;public class AnimationPlayControl : MonoBehaviour
{Animation ani;void Start(){PlayAnimation(ani, "Open",() =>{Debug.Log("动画播放前执行代码");},() =>{Debug.Log("动画播放完执行代码");});}// 封装函数public void PlayAnimation(Animation animation, string clipName, Action startAct = null, Action endAct = null){StartCoroutine(PlayAnimationItor(animation, clipName, startAct, endAct));}/// <summary>/// Animation动画播放迭代器/// </summary>/// <param name="animation">Animation组件</param>/// <param name="clipName">clip片段名</param>/// <param name="startAct">委托函数</param>/// <param name="endAct">委托函数</param>/// <returns></returns>IEnumerator PlayAnimationItor(Animation animation, string clipName, Action startAct, Action endAct){startAct?.Invoke();animation.Play(clipName);yield return new WaitForSeconds(animation[clipName].length);endAct?.Invoke();}
}
PS:主要是使用了协程中的new WaitForSeconds也就是等待X秒,这里就是等待动画播放的X秒后执行委托函数,更加详细的协程可以参考我其他文章,这里就不详细说明了。
2-2、第二种协程写法
using System;
using System.Collections;
using UnityEngine;public class AnimationPlayControl : MonoBehaviour
{Animation ani;void Start(){PlayAnimation(ani, "Open",() =>{Debug.Log("动画播放前执行代码");},() =>{Debug.Log("动画播放完执行代码");});}// 封装函数public void PlayAnimation(Animation animation, string clipName, Action startAct = null, Action endAct = null){StartCoroutine(PlayAnimationItor(animation, clipName, startAct, endAct));}/// <summary>/// Animation动画播放迭代器/// </summary>/// <param name="animation">Animation组件</param>/// <param name="clipName">clip片段名</param>/// <param name="startAct">委托函数</param>/// <param name="endAct">委托函数</param>/// <returns></returns>private IEnumerator PlayAnimationItor(Animation animation, string clipName, Action startAct, Action endAct){startAct?.Invoke();AnimationState animationState = animation[clipName];animation.Play(clipName);yield return StartCoroutine(new WaitForEndOfAnim(animationState));endAct?.Invoke();}
}// 实现WaitForEndOfAnim迭代器
public class WaitForEndOfAnim : IEnumerator
{AnimationState m_animState;public WaitForEndOfAnim(AnimationState animState){m_animState = animState;}public object Current{get{return null;}}public bool MoveNext(){return m_animState.enabled;}public void Reset(){}
}
这种方式,实现WaitForEndOfAnim迭代器,在动画播放完后执行后面的代码。
三、Animator动画播放结束判断
首先,要明白Animator是动画状态机,是用来控制动画片段,然后去切换动画片段的,如下图所示:

所以说,Animator默认就会开始播放一种动画,不论是Idle动画还是Walk动画,总会播放一种动画,所以就不用像Animation去Play某一个动画了,只需要判断当前动画是否播放完即可。
代码参考如下,两种方法写一起了:
using System;
using System.Collections;
using UnityEngine;public class AnimationPlayControl : MonoBehaviour
{Animator ani;void Start(){PlayAnimation(ani, "Open",() =>{Debug.Log("动画播放前执行代码");},() =>{Debug.Log("动画播放完执行代码");});}// 封装函数public void PlayAnimator(Animator animator, string clipName, Action startAct = null, Action endAct = null){StartCoroutine(PlayAnimationItor(animator, clipName, startAct, endAct));}/// <summary>/// Animation动画播放迭代器/// </summary>/// <param name="animation">Animation组件</param>/// <param name="clipName">clip片段名</param>/// <param name="startAct">委托函数</param>/// <param name="endAct">委托函数</param>/// <returns></returns>private IEnumerator PlayAnimationItor(Animator animator, string clipName, Action startAct, Action endAct){startAct?.Invoke();AnimatorStateInfo animatorStateInfo = animator.GetCurrentAnimatorStateInfo(0);yield return StartCoroutine(new WaitForEndOfAnimr(animatorStateInfo,clipName));endAct?.Invoke();}/// <summary>/// Animation动画播放迭代器/// </summary>/// <param name="animation">Animation组件</param>/// <param name="clipName">clip片段名</param>/// <param name="startAct">委托函数</param>/// <param name="endAct">委托函数</param>/// <returns></returns>IEnumerator PlayAnimationItor2(Animator animator, string clipName, Action startAct, Action endAct){startAct?.Invoke();yield return new WaitForSeconds(animator.GetCurrentAnimatorClipInfo(0)[0].clip.length);endAct?.Invoke();}
}// 实现WaitForEndOfAnim迭代器
public class WaitForEndOfAnimr : IEnumerator
{AnimatorStateInfo m_animState;public WaitForEndOfAnimr(AnimatorStateInfo animState,string clipName){m_animState = animState;}public object Current{get{return null;}}public bool MoveNext(){return m_animState.IsName(clipName);}public void Reset(){}
}
四、后记
结束,本篇文章讲解了Animation和Animator动画播放结束的判断代码。
以及如何实现在Animation和Animator动画播放结束判断,并且执行回调函数的实现。
你的点赞就是对博主的支持,有问题记得留言:
博主主页有联系方式。
博主还有跟多宝藏文章等待你的发掘哦:
| 专栏 | 方向 | 简介 |
|---|---|---|
| Unity3D开发小游戏 | 小游戏开发教程 | 分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。 |
| Unity3D从入门到进阶 | 入门 | 从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。 |
| Unity3D之UGUI | UGUI | Unity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。 |
| Unity3D之读取数据 | 文件读取 | 使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。 |
| Unity3D之数据集合 | 数据集合 | 数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。 |
| Unity3D之VR/AR(虚拟仿真)开发 | 虚拟仿真 | 总结博主工作常见的虚拟仿真需求进行案例讲解。 |
| Unity3D之插件 | 插件 | 主要分享在Unity开发中用到的一些插件使用方法,插件介绍等 |
| Unity3D之日常开发 | 日常记录 | 主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等 |
| Unity3D之日常BUG | 日常记录 | 记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。 |
相关文章:
【Unity3D小技巧】Unity3D中判断Animation以及Animator动画播放结束,以及动画播放结束之后执行函数
推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 在日常开发中,可能会遇到要判断Animation或者Anima…...
【1】熟悉刷题平台操作
TestBench使用 与quartus中testbench的写法有些许。或者说这是平台特有的特性!! 1 平台使用谨记 (1)必须删除:若设计为组合逻辑,需将自动生成的clk删除 若不删除,会提示运行超时错误。 &#…...
计算机网络:RIP协议以及距离向量算法
RIP协议 RIP是一种分布式的基于适量向量的路由选择协议,最大优点是简单。要求网络中的每一个路由器都要维护从它自己到其他每一个目的网络的唯一最佳(最短)距离记录,最多包含15个路由器,距离为16就表示网络不可达&…...
[数据结构与算法(严蔚敏 C语言第二版)]第1章 绪论(课后习题+答案解析)
1. 简述下列概念:数据、数据元素、数据项、数据对象、数据结构、逻辑结构、存储结构、抽象数据类型。 数据 数据是客观事物的符号表示,是所有能输人到计算机中并被计算机程序处理的符号的总称。数据是信息的载体,能够被计算机识别、存储和加工 数据元素…...
JS_countup.js 的简单使用,数字滚动效果
countup.js countup.js 是一个轻量级,无依赖的JavaScript类,通过简单的设置就可以达到数字滚动的效果 官网:https://inorganik.github.io/countUp.js/ 源码 var CountUpfunction(target,startVal,endVal,decimals,duration,options){var …...
【C++知识点】STL 容器总结
✍个人博客:https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 📚专栏地址:C/C知识点 📣专栏定位:整理一下 C 相关的知识点,供大家学习参考~ ❤️如果有收获的话,欢迎点赞👍…...
C++---背包模型---装箱问题(每日一道算法2023.3.9)
注意事项: 本题是"动态规划—01背包"的扩展题,dp和优化思路不多赘述。 题目: 有一个箱子容量为 V,同时有 n 个物品,每个物品有一个体积(正整数)。 要求 n 个物品中,任取若…...
if-else if与switch的练习1:输入两个数,输出两个数的加减乘除的值
1.if-else if的练习 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice…...
【教程】你现在还不知道微软的New Bing?你out了,快点进来看
哈喽啊,大家好,好久不见,我是木易巷! 不禁感叹,AI人工智能时代真的已经来临! 目前,谷歌和微软就各自面向大众的产品发布了重大公告。谷歌推出了一款名为Bard实验性对话式 AI 服务,而…...
https流程
ssl加密协议包含以下4个步骤 1、服务器去第三方机构注册生成证书,第三方机构非对称加密生成公钥私钥,给服务器一个私钥,证书包含了公钥。 2、客户端向服务器索要证书 3、客户端向第三方机构验证证书 4、客户端对称加密生成密钥,在…...
python魔法方法
Python中的魔法方法(也称为特殊方法或双下划线方法)是在类定义中使用的一些特殊的函数,可以使用dir方法查询。它们以双下划线开头和结尾,例如__init__和__str__。这些方法被Python解释器用于执行特定的操作,例如实例化对象、字符串…...
软件测试员如何进行产品测试?
一般来讲,当软件成为一个成功的产品后,产品测试工作就会复杂很多。比如拥有的用户量大,迭代频繁,测试的周期短,重复性强。面对紧张复杂的产品测试工作,软件测试员应怎样完成这一系列的测试工作呢࿱…...
计算机网络基础知识点【1】
文章目录计算机网络第一章 计算机网络参考模型1.计算机网络为什么需要分层?1.1 分层思想1.2 分层好处2.OSI七层模型2.1 OSI七层模型总结2.2 OSI七层工作原理2.3 数据封装与解封装2.4 计算机网络常用协议3.TCP/IP参考模型3.1 什么是TCP/IP协议3.2 TCP/IP协议族的组成…...
c++ 中标准库类型 string 详解
👁🗨👁🗨 前言 标准库类型string 表示可变长的字符序列,使用string 类型必须首先包含string 头文件。string 定义在命名空间std 中。 定义和初始化 string 对象 首先说明如何初始化对象是由类本身决定的࿰…...
Html新增属性之拖拽(drag)
元素在拖放过程中触发的事件 HTML5中,只要将元素的 draggable 属性设置为 true 就可以实现拖放功能,在拖放过程中,触发了多个事件,如下: dragstart:事件主体是被拖放元素,在开始拖放被拖放元素时触发。dra…...
C/C++开发,无可避免的多线程(篇二).thread与其支持库
一、原子类型与原子操作 1.1 原子类型与操作介绍 在前一篇博文中,多线程交互示例代码中,给出了一个原子类型定义: // 原子数据类型 atomic_llong total {0}; 那么什么事原子数据类型呢,和c的基础数据类型有什么不同呢:…...
mysql数据库之表级锁
表级锁,每次操作锁住整张表。锁定粒度大,发生所冲突的概率最高,并发度最低。应用在myisam、innodb、bdb等存储引擎中。 一、表级锁分类。 1、表锁 2、元数据锁(meta data lock,MDL) 3、意向锁 二、表锁…...
Python - Pandas - 数据分析(2)
Pandas数据分析2前言常用的21种统计方法describe():numeric_only:偏度skewness:功能:含义:计算公式:演示:峰度值:用途:数值:计算公式:演示&#x…...
我的十年编程路 2019年篇
随着2018年,三星天津研究院的裁撤,我选择了到广州的三星研究院工作,与最心爱的她开始一起生活。 这一年的开始,我注册了博客园。和2014年类似,在刚注册不久,我写了一篇题为《全新开始,全心出发…...
(蓝桥真题)剪格子(搜索+剪枝)
样例1输入: 3 3 10 1 52 20 30 1 1 2 3 样例1输出: 3 样例2输入: 4 3 1 1 1 1 1 30 80 2 1 1 1 100 样例2输出: 10 分析:这道题目我们直接从(1,1)点开始进行dfs搜索即可,但是需要注意一点的是我们搜…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...
GraphQL 实战篇:Apollo Client 配置与缓存
GraphQL 实战篇:Apollo Client 配置与缓存 上一篇:GraphQL 入门篇:基础查询语法 依旧和上一篇的笔记一样,主实操,没啥过多的细节讲解,代码具体在: https://github.com/GoldenaArcher/graphql…...
