Unity Animation System 动画播放控制

0x00

这是又一次翻以前的代码,用协程写了控制动画播放的逻辑,比如通过时间,检测动画是否播放完成等等。

为了更加通用的场景,这次决定用 Animation Event 来实现,进行尝试。

前面有用过一个 UIEventListener 的脚本组件作为 UI 对象统一添加事件,感兴趣可以点这里去看看……

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更新顺序的问题,扑街,那时候了解了其实要进行这种操作,在控制器脚本的位置进行处理时最好的,在事件发生时转到控制器脚本进行处理就可以了,是我之前的一篇文章里的解决方案。(好像都是在处理事件的时候出现的诶)。

这次又是同样,其实是一个尝试性的需求,同时对四个对象进行相同的操作,让他们同时访问了同一个当前值作为显示,用同一个值进行检测判断停止,然后……反正就跑起来很诡异了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值