使用Unity的动画事件时需要注意的“坑”
当我们需要根据当前动画状态执行一些事件的时候,我们往往会需要使用动画事件。
我们可能会使用下面的方法
对动画添加动画事件,当进入动画时调用 OnEnterAnimation 方法
var clips = this.animator.runtimeAnimatorController.animationClips; for (int i = 0; i < clips.Length; i++) { var clip = clips[i]; AnimationEvent e = new AnimationEvent() { time = 0, functionName = "OnEnterAnimation", }; clip.AddEvent(e); } this.animator.Rebind()
然后在 OnEnterAnimation 里面去更新记录状态信息
// 上一次的状态 int hashLast; // 当前进入的动画的状态 int hashCurrent; public void OnEnterAnimation() { hashLast = hashCurrent; hashCurrent = this.animator.GetCurrentAnimatorStateInfo(0).shortNameHash; // do something.... }
然后根据 每一次更新的 当前状态与上一次状态去调用相应的事件。
但是这里有一个坑:当进入某个动画的时候,调用 this.animator.GetCurrentAnimatorStateInfo(0) 方法返回的状态信息中的 shortNameHash 并没有更新到当前播放的动画。
这里我们修改上面绑定的事件进行验证
// 添加动画事件 var clips = this.animator.runtimeAnimatorController.animationClips; for (int i = 0; i < clips.Length; i++) { var clip = clips[i]; AnimationEvent e = new AnimationEvent() { time = 0, functionName = "OnEnterAnimation", stringParameter = clip.name }; clip.AddEvent(e); } this.animator.Rebind() // 添加的事件 与 相关字段 // 上一个的动画 string animationLast; // 当前动画 string animationCurrent; public void OnEnterAnimation(string name) { animationLast = animationCurrent; animationCurrent = name; var animationCurrentByStateInfo = animator.GetCurrentAnimatorStateInfo(0).shortNameHash.ToNameFromHash(); Debug.Log("进入动画 {}\t离开动画{}\t动画控制器StateInfo{}" .format( animationCurrent , animationLast , animationCurrentByStateInfo) ); }
可以看到第二行,播放Fight_attack动画时,动画控制器的状态同步到 Fight_attack
而第三行,进入Fight_idle动画时,动画控制器却还没有同步到 Idle状态。
因为时间关系目前没有去深究,猜测应该是因为勾选了动画控制器的 HasExitTime,所以开始播放这个动画的时候没有完全离开上一个动画。
解决办法就是调用事件的时候传入动画名称,而不去依赖Animator.GetCurrentAnimatorStateInfo
上文代码中的 format 和 ToNameFromHash() 是自己实现的扩展方法,所以直接复制粘贴没法运行。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)