翻译自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. K8s集群安全机制

    安全机制说明 k8s作为一个分布式集群管理的工具,保证集群的安全性是其一个重要的任务.API Server是集群内部各个组件通信的中介,也是外部控制的入口,,所以K8s的安全机制就是围绕保护API S ...

  2. vue 数据没更新/dom没更新/样式没更新的各种解决方式

    1.用 $forceUpdate() 强制更新 2.用 this.$set(obj, key, value)/vue.set(obj, key, value) 向响应式对象中添加一个 property ...

  3. Unix时间戳转化成普通日期

    var time = 1630634462000; //13位数 var unixTimestamp = new Date(time); var commonTime = unixTimestamp. ...

  4. Unity UI 识别画圆手势

    最近做了一个项目,需要打开一个编辑UI,平时不显示,如果在UI界面上做一个按钮,感觉很丑,就想到了Reporter_Logs的画圆触发. 识别到你在界面上画了一个圆 (可用于 Windows 和 An ...

  5. iOS开发之UIImage在压缩时失真问题,压缩图片的大小

    今天遇到UIImage在压缩时失真问题,压缩图片的大小图片模糊 错误的方案 /** * 压缩图片 * image:将要压缩的图片 size:压缩后的尺寸 */ -(UIImage*) OriginIm ...

  6. 重启nginx 报错 nginx.pid

    先检查 nginx -c /etc/nginx/nginx.conf 看看端口是否被占用 若占用杀掉 ps -ef | grep nginx kill --- 然后再用nginx -c /etc/ng ...

  7. 如何使用命令行直接运行PHP脚本程序

    在我的博客里有一些文章是和解码或者处理文件有关,其中有些自动化工作比较简单,使用了一些PHP程序来编写处理,这样写起程序来也比较快,因为是纯过程的任务,不想用C#来处理. 写完PHP的脚本程序后,保存 ...

  8. react fiber 的运行机制

    前言 1. 不同的元素类型决定不同的任务类型 2. react 的元素类型有 class component , function component ,Dom nodes, portal等等 要理解 ...

  9. application.yaml

    spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver username: root password: root url: j ...

  10. @Async 注解的使用

    1.@Async介绍 在Spring中,基于@Async标注的方法,称之为异步方法:这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作 例如, 在某个调用中, ...