当前位置: 首页 > news >正文

【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之UGUIUGUIUnity的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插件分享简书地址我的个人博客 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 在日常开发中&#xff0c;可能会遇到要判断Animation或者Anima…...

【1】熟悉刷题平台操作

TestBench使用 与quartus中testbench的写法有些许。或者说这是平台特有的特性&#xff01;&#xff01; 1 平台使用谨记 &#xff08;1&#xff09;必须删除&#xff1a;若设计为组合逻辑&#xff0c;需将自动生成的clk删除 若不删除&#xff0c;会提示运行超时错误。 &#…...

计算机网络:RIP协议以及距离向量算法

RIP协议 RIP是一种分布式的基于适量向量的路由选择协议&#xff0c;最大优点是简单。要求网络中的每一个路由器都要维护从它自己到其他每一个目的网络的唯一最佳&#xff08;最短&#xff09;距离记录&#xff0c;最多包含15个路由器&#xff0c;距离为16就表示网络不可达&…...

[数据结构与算法(严蔚敏 C语言第二版)]第1章 绪论(课后习题+答案解析)

1. 简述下列概念:数据、数据元素、数据项、数据对象、数据结构、逻辑结构、存储结构、抽象数据类型。 数据 数据是客观事物的符号表示&#xff0c;是所有能输人到计算机中并被计算机程序处理的符号的总称。数据是信息的载体&#xff0c;能够被计算机识别、存储和加工 数据元素…...

JS_countup.js 的简单使用,数字滚动效果

countup.js countup.js 是一个轻量级&#xff0c;无依赖的JavaScript类&#xff0c;通过简单的设置就可以达到数字滚动的效果 官网&#xff1a;https://inorganik.github.io/countUp.js/ 源码 var CountUpfunction(target,startVal,endVal,decimals,duration,options){var …...

【C++知识点】STL 容器总结

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4da;专栏地址&#xff1a;C/C知识点 &#x1f4e3;专栏定位&#xff1a;整理一下 C 相关的知识点&#xff0c;供大家学习参考~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;…...

C++---背包模型---装箱问题(每日一道算法2023.3.9)

注意事项&#xff1a; 本题是"动态规划—01背包"的扩展题&#xff0c;dp和优化思路不多赘述。 题目&#xff1a; 有一个箱子容量为 V&#xff0c;同时有 n 个物品&#xff0c;每个物品有一个体积&#xff08;正整数&#xff09;。 要求 n 个物品中&#xff0c;任取若…...

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了,快点进来看

哈喽啊&#xff0c;大家好&#xff0c;好久不见&#xff0c;我是木易巷&#xff01; 不禁感叹&#xff0c;AI人工智能时代真的已经来临&#xff01; 目前&#xff0c;谷歌和微软就各自面向大众的产品发布了重大公告。谷歌推出了一款名为Bard实验性对话式 AI 服务&#xff0c;而…...

https流程

ssl加密协议包含以下4个步骤 1、服务器去第三方机构注册生成证书&#xff0c;第三方机构非对称加密生成公钥私钥&#xff0c;给服务器一个私钥&#xff0c;证书包含了公钥。 2、客户端向服务器索要证书 3、客户端向第三方机构验证证书 4、客户端对称加密生成密钥&#xff0c;在…...

python魔法方法

Python中的魔法方法&#xff08;也称为特殊方法或双下划线方法&#xff09;是在类定义中使用的一些特殊的函数,可以使用dir方法查询。它们以双下划线开头和结尾&#xff0c;例如__init__和__str__。这些方法被Python解释器用于执行特定的操作&#xff0c;例如实例化对象、字符串…...

软件测试员如何进行产品测试?

一般来讲&#xff0c;当软件成为一个成功的产品后&#xff0c;产品测试工作就会复杂很多。比如拥有的用户量大&#xff0c;迭代频繁&#xff0c;测试的周期短&#xff0c;重复性强。面对紧张复杂的产品测试工作&#xff0c;软件测试员应怎样完成这一系列的测试工作呢&#xff1…...

计算机网络基础知识点【1】

文章目录计算机网络第一章 计算机网络参考模型1.计算机网络为什么需要分层&#xff1f;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 详解

&#x1f441;‍&#x1f5e8;&#x1f441;‍&#x1f5e8; 前言 标准库类型string 表示可变长的字符序列&#xff0c;使用string 类型必须首先包含string 头文件。string 定义在命名空间std 中。 定义和初始化 string 对象 首先说明如何初始化对象是由类本身决定的&#xff0…...

Html新增属性之拖拽(drag)

元素在拖放过程中触发的事件 HTML5中&#xff0c;只要将元素的 draggable 属性设置为 true 就可以实现拖放功能&#xff0c;在拖放过程中&#xff0c;触发了多个事件&#xff0c;如下&#xff1a; dragstart:事件主体是被拖放元素&#xff0c;在开始拖放被拖放元素时触发。dra…...

C/C++开发,无可避免的多线程(篇二).thread与其支持库

一、原子类型与原子操作 1.1 原子类型与操作介绍 在前一篇博文中&#xff0c;多线程交互示例代码中&#xff0c;给出了一个原子类型定义&#xff1a; // 原子数据类型 atomic_llong total {0}; 那么什么事原子数据类型呢&#xff0c;和c的基础数据类型有什么不同呢&#xff1a…...

mysql数据库之表级锁

表级锁&#xff0c;每次操作锁住整张表。锁定粒度大&#xff0c;发生所冲突的概率最高&#xff0c;并发度最低。应用在myisam、innodb、bdb等存储引擎中。 一、表级锁分类。 1、表锁 2、元数据锁&#xff08;meta data lock&#xff0c;MDL&#xff09; 3、意向锁 二、表锁…...

Python - Pandas - 数据分析(2)

Pandas数据分析2前言常用的21种统计方法describe()&#xff1a;numeric_only&#xff1a;偏度skewness&#xff1a;功能&#xff1a;含义&#xff1a;计算公式&#xff1a;演示&#xff1a;峰度值&#xff1a;用途&#xff1a;数值&#xff1a;计算公式&#xff1a;演示&#x…...

我的十年编程路 2019年篇

随着2018年&#xff0c;三星天津研究院的裁撤&#xff0c;我选择了到广州的三星研究院工作&#xff0c;与最心爱的她开始一起生活。 这一年的开始&#xff0c;我注册了博客园。和2014年类似&#xff0c;在刚注册不久&#xff0c;我写了一篇题为《全新开始&#xff0c;全心出发…...

(蓝桥真题)剪格子(搜索+剪枝)

样例1输入&#xff1a; 3 3 10 1 52 20 30 1 1 2 3 样例1输出&#xff1a; 3 样例2输入&#xff1a; 4 3 1 1 1 1 1 30 80 2 1 1 1 100 样例2输出&#xff1a; 10 分析&#xff1a;这道题目我们直接从(1,1)点开始进行dfs搜索即可&#xff0c;但是需要注意一点的是我们搜…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...