0x00
这是又一次翻以前的代码,用协程写了控制动画播放的逻辑,比如通过时间,检测动画是否播放完成等等。
为了更加通用的场景,这次决定用 Animation Event 来实现,进行尝试。
0x01
在开发过程中,判断一个动画是否播放完成是一个常见的需求,如何在 Unity 中处理这些,首先来解决这些小问题:
- 控制播放流
在 Animator 组件中,播放特定动画片段
animator.Play(string stateName, int layer, float normalizedTime);
- 停止播放
animator.speed = 0;
- 获取当前状态机的全部动画片段(AnimationClip[])
var clips = animator.runtimeAnimatorController.animationClips;
- 获取当前播放的动画片段
animator.GetCurrentAnimatorClipInfo();
- 获取当前播放的动画信息
AnimatorClipInfo info = anim.GetCurrentAnimatorStateInfo(0);
if (info.IsName(statename)){
...
}
0x02
使用 Animation Event,在动画 Animation clip 中添加
(1)在编辑器中添加
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NQwB37Ps-1589818082830)(addEvent.png)]
此处添在动画结尾处添加了一个事件,回调 AnimCallback 函数。
对于动画事件的回调函数,必须是在 Animator 组件同级的脚本组件中的公共方法。
(2)在代码中添加动画事件
限制:只能在 animator 同级的 gameobject 绑定组件回调函数
目前的解决方法是通过添加事件分发的组件,来回调当前控制器中的事件处理程序。
同时要修改 clip 转换的参数设置
using UnityEngine;
public class AnimationEventTrigger : MonoBehaviour
{
public delegate void AnimDelegate(GameObject go, AnimatorStateInfo info);
public event AnimDelegate AnimOnEvent;
public static AnimationEventTrigger GetListener(GameObject go)
{
AnimationEventTrigger listener = go.GetComponent<AnimationEventTrigger>();
if (null == listener)
{
listener = go.AddComponent<AnimationEventTrigger>();
}
return listener;
}
public void AddEventToClip(string clipName, float triggerTime)
{
var animator = gameObject.GetComponent<Animator>();
if (animator != null)
{
AnimationEvent evt = new AnimationEvent()
{
time = triggerTime,
functionName = "AnimCallback",
};
var clips = animator.runtimeAnimatorController.animationClips;
foreach (var c in clips)
{
if (c.name == clipName)
{
c.AddEvent(evt);
}
}
}
}
public void AnimCallback()
{
if (null != AnimOnEvent)
{
AnimOnEvent(gameObject, gameObject.GetComponent<Animator>().GetCurrentAnimatorStateInfo(0));
}
}
}
0x03
其他问题:
在 Game 视图下,对动画中子对象激活状态的控制无效,测试时 起始状态为无效时就能正常显示,否则显示动画显示错误。
在对象没有激活时,是没有办法获取到对象的组件的。
0x04
很多时候不犯错是记不得的,
很多时候很久没犯错也会忘记了错误是怎么避免的,
可能不对,但我就是想瞎白话。
絮叨模式开启,
我作为菜狗子经常犯的错误是让不同的对象同时访问同一份数据,期望他们足够聪明,能知道我想让谁先用,并且,别把东西弄坏了,任何东西,但是……
好吧,感觉多线程要解决的就是这个问题吧。
之所以这么说,是因为前段时间有做一个上色的小功能,当时在区分不同区域时用了 static 原本是想作为标记,因为所有公用一个变量,让我觉得是互斥的关系,也就同一时刻,无论是谁修改了这个值,大家都知道了,但碰上了update更新顺序的问题,扑街,那时候了解了其实要进行这种操作,在控制器脚本的位置进行处理时最好的,在事件发生时转到控制器脚本进行处理就可以了,是我之前的一篇文章里的解决方案。(好像都是在处理事件的时候出现的诶)。
这次又是同样,其实是一个尝试性的需求,同时对四个对象进行相同的操作,让他们同时访问了同一个当前值作为显示,用同一个值进行检测判断停止,然后……反正就跑起来很诡异了。