翻译自https://blogs.unity3d.com/2016/07/13/wait-ive-changed-my-mind-state-machine-transition-interruptions/?_ga=2.41883234.177090268.1554974117-1023672624.1552526721

转载自:https://blog.csdn.net/su9257/article/details/53678245/

看了官方相关文档,第一遍看,没太关注这一部分。再次看,感觉有点东西。让我想起来,LOL中的取消普攻的玩法,发现就是这一技术实现的。动画转换之间不再是直来直去,而是可以多样控制。这篇文章,翻译自unity3d官方API(https://docs.unity3d.com/Manual/class-Transition.html#TransitionInterruption)中提到的一篇英文博客。

--------------

本文将由Unity工程师Catherine Proulx,为大家深入讲解状态机的转换和中断相关的细节。

最近处理了一个用户报告的很棘手的Bug,这个Bug涉及到空状态、覆盖层和转换中断的组合。当进一步深入研究这个Bug的时候,我注意到动画系统文档中关于转换中断的描述太抽象了。在和团队进行深度沟通后,我们决定发布博文说明一下转换中断。

下面我们来深入研究一下状态机的转换和中断的细节。

默认情况下,在动画系统中,转换是不能被中断的:一旦开始由一个状态转换为另一个状态,这个过程没有出口。就像一个乘坐飞越大西洋航班的乘客,只能舒适的靠在座位上直到抵达目的地,不能改变自己的目的地。对大多数用户来说,这是好事。

但是如果需要对转换过程有更多控制,也可以通过使用多种不同方式配置Mecanim来满足需求。如果对当前目的地不满意,可以跳到驾驶员的位置在中途改变飞行计划。这意味着响应动画更多,同时也意味着很有可能会迷失在这复杂的情况中。

下面通过几个例子来说明一下。首先是一个简单的包含4个状态的状态机,标记为A到D,并且触发器都对应了状态机上的每个转换。

默认情况下,当触发了A->B的转换后,状态机会将状态从A转换为B,并且没什么可以阻止它最终变为状态B。但是如果打开A->B转换的检视面板,并将Interruption Source(中断源)从“None(无)”变为“Current State(当前状态)”后,从A到B的这个过程就可以被状态A的某些触发器中断了。

为什么是“某些”触发器?因为“Ordered Interruption(顺序中断)”默认情况下是勾选的。这意味着在状态A的转换过程中,只有比当前转换优先级更高的转换能够被执行。通过查看状态A的检视面板可以知道,只有 A->C这个转换的优先级比A->B高。

因此如果触发了A->B,马上又触发了A->D,那么转换过程不会被中断。然而如果后触发的是A->C,那么A->B的转换会被马上中断并且状态机会转换至状态C。

在内部,动画系统记录了中断发生时的姿势,并且将静态的姿势(X)和新的目标动画进行合成。

为什么是静态姿势,而不是在当前转换和新转换之间进行可能更流畅的融合?简单来说:性能原因。当游戏面临中断的级联时,同时持续追踪很多正在进行的动态转换将使得动画系统不可扩展(因为每增加一个新状态都会消耗更多的系统资源)。

现在,如果取消勾选“Ordered Interruption(顺序中断)”,那么A->C和A->D都可以中断A->B的转换。但如果它们在同一帧触发,那么A->C仍然会优先执行,因为A->C的优先级更高。

如果将中断源改为“Next State(下一状态)”,A->C和A->D将不再中断转换,不论它们的顺序如何。但是如果触发了B->D,则会马上开始A到D的转换,并不会完成到B的转换。

转换顺序对于状态B来说也很重要。“Ordered Interruption(顺序中断)”的勾选已经不能用了(任何从状态B触发的转换都可以中断A->B的转换,因为它们都没有相对于A->B的优先级排序),但状态B的转换顺序会决定在同一帧都被触发的情况下最终将转换到哪个状态。在这个例子中,如果B->D 和 B->C在同一帧触发了, 则B->D会被选中。

最后,为了实现完全控制,可以将中断源设置为“Current State Then Next State(先当前状态再下一状态)”或者“Next State Then Current State(先下一状态再当前状态)”。在这种情况下,转换会先在一个状态下独立分析,然后再到另一个状态。

所以,如果使用如下配置:

在状态A到B的转换过程中,有个很激动的玩家在同一帧触发了4次转换:A->C,A->D,B->C,B->D。结果如何呢?

首先,勾选了“Ordered Interruption”,所以可以直接忽视A->D,因为它的优先级不如A->B高。当前状态会最先处理,所以不用看A->B了,这里进行的是A->C的转换。

但是,相同配置条件下,如果只触发了B->C和B->D,那就会进行B->D的转换(它比B->C的优先级高)。

现在还只是一个转换,所有其他的转换也是可能以其特定的规则被中断的。所以如果让A->C的转换从下一个状态中断,那可能A->B的转换会被A->C中断,而反过来A->C的转换也可能会被C->D中断。

有一点很重要,不管中断在何处发生,原状态会保持不变直至转换结束,而Animator.GetCurrentAnimatorStateInfo()将始终返回起始状态。

简而言之,状态转换的中断设置非常强大,也提供了极高的灵活性,但也会让人非常迷惑。所以要明智地使用状态转换中断,有疑问一定要现在编辑器中测试。

Unity3d 动画转换中断的更多相关文章

  1. React-router4 第八篇 ReactCSSTransitionGroup 动画转换

    https://reacttraining.com/react-router/web/example/animated-transitions 动画转换这么高级,其实是又引入了一个组件,没什么特别, ...

  2. Bodymovin:Bodymovin和Lottie:把AE动画转换成HTML5/Android/iOS原生动画

    转自:https://www.cnblogs.com/zamhown/p/6688369.html 大杀器Bodymovin和Lottie:把AE动画转换成HTML5/Android/iOS原生动画 ...

  3. unity3d 动画卡帧 动画合成 动画层次

    2013-02-26 16:22 2059人阅读 评论(0) 收藏 举报 unity3d 中动画的添加   http://unity3d.com/support/documentation/Manua ...

  4. Unity3d动画脚本 Animation Scripting(深入了解游戏引擎中的动画处理原理)

    也许这一篇文章的内容有点枯燥,但我要说的是如果你想深入的了解游戏引擎是如何处理动画片断或者素材并 让玩家操控的角色动起来栩栩如生,那么这真是一篇好文章(当然我仅仅是翻译了一下)   动画脚本 Anim ...

  5. Unity3D动画面板编辑器状态属性对照表

    不推荐用AnimationUtility.SetEditorCurve问题很多,推荐AnimationCurve.AddKey.通过AnimationUtility.GetAllCurves可以获得编 ...

  6. Unity3D 动画回调方法

    最近发现很多coder.在用Unity开发游戏的时候都需要一个需求就是..动画播到某一帧就要干什么事情.而且希望能得到回调. 在unity里面的window菜单有个.Animation工具.打开它.然 ...

  7. Unity3D 动画状态简单控制核心代码

    状态机是这样的 包含静止.跑.攻击.死亡四个动画 下面是核心代码(PS:代码高亮插件出问题了,将就看一下吧..) AnimatorStateInfo stateInfo = m_ani.GetCurr ...

  8. 大杀器Bodymovin和Lottie:把AE动画转换成HTML5/Android/iOS原生动画

    前段时间听部门老大说,Airbnb出了个移动端的动画库Lottie,可以和一个名叫Bodymovin的AE插件结合起来,把在AE上做好的动画导出为json文件,然后以Android/iOS原生动画的形 ...

  9. 反混淆、反编译unity3d动画插件DFTweenLite得到源代码

    出处:http://blog.csdn.net/u010019717 author:孙广东      时间:2015.3.17   23:00 我为什么要得到这个源代码.由于有洁癖! 对于Itween ...

  10. [技术博客]Unity3d 动画控制

    在制作游戏时,导入的箱子模型本身自带动画.然而,它的动画是一个从打开到关闭的完整过程,并且没有给出控制打开关闭的方法. 最直接的想法是对该动画进行拆分,再封装成不同的动画状态,但是不巧的是,这个动画被 ...

随机推荐

  1. Vulnhub:vulnuni1.0.1靶机

    kali:192.168.111.111 靶机:192.168.111.192 信息收集 端口扫描 nmap -A -v -sV -T5 -p- --script=http-enum 192.168. ...

  2. 「JOI Open 2022」Giraffes 题解

    设我们将要给出的观感好的排列为 \(q\),我们希望求出 \(\sum[p_i=q_i]\) 的最大值(这里指不移动的长颈鹿个数). 结论一:当且仅当左右端点有当前区间最大值或者最小值时条件才能成立. ...

  3. 【Nginx】优化,增加线程

    https://blog.csdn.net/cnskylee/article/details/127645806 众所周知,Nginx一款体积小巧,但是性能强大的软负载,主要被用作后端服务和应用的反向 ...

  4. CodeGym自学笔记02——打印命令

    1.方法的主体由命令组成.我们甚至可以说,方法就是一组被赋予名称(方法名称)的命令. 2.如果你使用几次 System.out.println() 命令,就会发现每次传递给该命令的文本都会显示在单独的 ...

  5. Django 之 ModelForm

    一 Django的form组件 forms组件 二 Django的model form组件 这是一个神奇的组件,通过名字我们可以看出来,这个组件的功能就是把model和form组合起来,先来一个简单的 ...

  6. spring boot No qualifying bean of type 'org.apache.catalina.core.ApplicationContext' available

    发现创建的ApplictionContext对象还没有containsBean的方法, 找了很久没搞定,后面发现原来是包导入错了. 应该导入 import org.springframework.co ...

  7. java 注解基础

    java 内置注解 注解 作用 描述 @Override 将覆盖父类中的方法 作用在子类的方法上 @Deprecated 代码被弃用 使用了被@Deprecated注解的代码则编译器将发出警告 @Su ...

  8. js,php中的面向对象

    面向对象 js中的面向对象: 面向对象(OOP):通过函数封装得到的一个类 1.类的本质还是函数 每个类(函数)天生有一个prototype的属性,这个prototype又是一个对象,这个对象里有个c ...

  9. windows 系统进行升级之后,如何删除 Windows.old 文件夹。

    首先用鼠标右键点击 C 盘,在弹出的下拉列表里找到"属性"并点击它. 步骤阅读 2 在打开的 C 盘属性里的常规找到"磁盘清理",点击它打开. 步骤阅读 3 这 ...

  10. linux 下彻底删除MySQL

    1.查找以前是否装有mysql 命令:rpm -qa|grep -i mysql 2.停止mysql服务.删除之前安装的mysql 删除命令:rpm -e –nodeps 包名 # rpm -ev M ...