Unity 2D - 平滑停止动画循环

时间:2017-03-09 18:05:53

标签: c# animation unity3d unity5 unity2d

所以,我有一个屏幕,显示一个覆盖整个屏幕的动画。

现在,我有7个循环动画,所有动画都以同一帧开始和结束以保持兼容性。但是我如何能够按下按钮后我可以等待每个动画在下一个动画播放之前完成所以它看起来很流畅?

3 个答案:

答案 0 :(得分:0)

您可以为每个动画脚本添加一个自定义变量。这些变量应该与您想要的顺序完全匹配。当每个动画结束时,为该变量分配一个自定义值,并根据您刚刚分配的变量值启动下一个动画脚本。

答案 1 :(得分:0)

你需要解决的第一件事是动画师控制器。该动画控制器知道可以播放的所有必要动画。如果你不想要的话,你就不必把它连接起来,因为它可以以任何顺序播放7个动画......这就是很多链接。

为了让它工作,你的动画师控制器需要表示每次转换的bool参数,所以当你从脚本设置它们时,控制器将按照它应该的方向移动。要进行转换,当剪辑到达结尾时,将转换退出时间设置为1.请记住,您仍然需要管理前端队列数据结构并在转换开始时重置bool,此& #39; ll阻止它到达下一个状态并立即转换到另一个状态。

相反,您可以为此编写一个自定义处理程序,用于设置当前正在播放的动画。沿着这些方向的东西可以解决这个问题:

class YourAnimController : MonoBehaviour
{
       private Queue<int> queuedStateHashes = new Queue<int>();

       private int currentStateHash;

       public string defaultState;
       private int defaultHash;

       public Animator theAnimator;

       private void Awake()
       {
           defaultHash = Animator.StringToHash(defaultState);
           StartCoroutine(PlayStates());
       }

       //how you start and exit this is up to you, in this case, 
       //I'll assume it starts on awake
       private IEnumerator PlayStates()
       {
            while(true)
            {          
                SetAnimStates();

                yield return null;
            }                              
       }

       private void SetAnimState()
       {
           AnimatorStateInfo info = theAnimator.GetCurrentAnimatorStateInfo(0);

           if(queuedStates.Count > 0)
           {
               if(info.normalizedTime >= 1)
               {
                   currentStateHash = queuedStateHashes.Dequeue();

                   theAnimator.Play(currentStateHash, 0, 0);                                                                       
               }
           }               
           else if(currentStateHash != defaultStateHash)
           {
               queuedStateHashes.Enqueue(defaultStateHash);                  
           }                     
       }

       private void Update()
       {
            if(Input.GetButtonDown("Your button1"))
            {
                 int stateHash = Animator.StringToHash("First state");
                 queuedStateHashes.Enqueue(stateHash);                                         
            }
            //repeat for all additional anims
       }

       //Any other methods
}

现在解释一下: 队列用于排队要播放的状态,这允许它们按特定顺序播放,先来先发球。

可以将PlayStates方法逻辑转换为Update方法。您在输入检查后执行此操作,并且您将删除while循环。我这样做是因为它可以让你更好地控制它何时以及如何停止和启动,而更新将不断进行评估。如果您没有在队列中有任何状态,这种方法允许您关闭协程,如果您选择这样做。对你来说是一个挑战:)。当你按下按钮时别忘了重新启动它。

动画师状态信息抓取告诉我们动画师控制器中当前正在播放的内容。使用标准化时间是因为您需要知道动画的进展程度。标准化时间基本上是已播放的当前动画的百分比。为动画片段提供了循环功能,在这种情况下,它会告诉您它播放的百分比和次数。如果你有点好奇,请调试并亲眼看看。

需要修改此方法以将循环考虑在内,因此它只会在动画完成动画循环后更改动画。您可能需要修改此位:

if(info.normalizedTime >= 1 && queuedStates.Count > 0)

让它发挥作用,另一个挑战:)。

现在有些文件:

AnimatorStateInfo:https://docs.unity3d.com/ScriptReference/AnimatorStateInfo.html

队列: https://msdn.microsoft.com/en-us/library/7977ey2c(v=vs.110).aspx

动画: https://docs.unity3d.com/ScriptReference/Animator.html

动画控制器方法,遍布各处的链接,使用了类似的想法,实现起来可能比较棘手,设置控制器时耗时更多,而上面概述的方法不应该需要转换,如果要相信文件: https://docs.unity3d.com/ScriptReference/Experimental.Director.IAnimatorControllerPlayable.html

希望这会引导你朝着正确的方向前进。

答案 2 :(得分:0)

试试Animator.speed: https://docs.unity3d.com/ScriptReference/Animator-speed.html

你可以尝试Mathf.Lerf(1f,0f,0.5f),但我认为处理它可能很复杂。 :d