翻译自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. CF1744F MEX vs MED

    个人思路: 条件可以转化成长度为 \(x\) 的区间需要包含 \([0,\lfloor \frac{(x-1)}{2} \rfloor]\). 我们从小到大枚举每一个数 \(i\),计算长度为 \(i ...

  2. Redis入门级简单安装使用

      最近突然就想学一下Redis,于是就各种找教程,前两天实际操作了一下,也不是想象中的很难 但是今天想写一个使用Redis的demo,突然就不会使用Redis了,在网上也是查找了半天,还是想起来了点 ...

  3. [版本控制-Git]-git学习总结

    1.如何将本地的文件添加到已经建好的远程分支上: 1.1 本地文件夹内,右键-git bash - 创建新仓 git init 1.2 git remote add origin 远程仓库的githu ...

  4. c++获取类型信息

    获取类型信息 typeid typeid运算符用来获取一个表达式的类型信息. 对于基本类型数据, 类型信息比较简单, 主要指数据的类型; 对于对象(类类型的数据), 类型信息指: 对象所属的类, 所包 ...

  5. python 链接云端数据库/远程数据库 可以使用原始Odbc

    class MySqlOdbc: def __init__(self): self.sqlhead = None # 当前数据链接句柄 self.mycursor = None # 当前游标 &quo ...

  6. 如何将PDF文件中的部分信息隐藏或遮盖呢?

      由于工作需要,总是需要对PDF文件中的内容进行部分隐藏.之前,作为VIP,可以使用某软件对PDF中的信息进行部分遮盖,现在,VIP到期了,我也不想继续花钱了(哭穷,嘻嘻)   在信息时代,只要会百 ...

  7. 代码随想录训练营day 3|59.螺旋矩阵II 加 数组总结篇

    59.螺旋矩阵II 题目链接:59.螺旋矩阵II 题目描述:给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵. 示例: 输入: 3 输出: [ [ 1 ...

  8. vim下的查找命令

    linux下vim 查找命令: /text --查找text, 按n查找下一个, N查找上一个 ?text --查找text(反向查找), 按n查找下一个, N查找上一个 */# --查找光标当前的单 ...

  9. vue指令入门

    1.  vue属性.事件.内容绑定 1 <div id="dv"> 2 <!-- v-cloak能够解决表达式闪烁问题 3 (当网速较慢时,会先出现{{msg}} ...

  10. 通过expected_conditions判断网页元素是否存在

    expected_conditions模块: 是Selenium的一个子模块,selenium.webdriver.support.expected_conditions 可以对网页上元素是否存在进行 ...