2017-03-09 291 views
0

所以,我有一個屏幕顯示覆蓋整個屏幕的動畫。Unity 2D - 平滑停止循環動畫

現在,我有7個循環動畫,所有的開始和結束在同一幀兼容性。但是我怎樣才能做到這一點,按下按鈕後,我可以等待每個動畫完成,然後播放下一個動畫,看起來很流暢?

+0

你能發表一些代碼嗎? – LaneL

+0

對不起,這裏還沒有代碼,因爲我還沒有想出一個好方法。動畫事件看起來不錯,但也有點過分 – uncanny

回答

0

你需要首先解決的是動畫控制器。該動畫製作者控制器知道可以播放的所有必要動畫。如果你不想要,你不需要連接任何東西,因爲它代表了可以以任何順序播放的7個動畫...這是很多鏈接。

爲了讓它工作,您的動畫師控制器需要代表每個轉換的bool參數,因此,當您通過腳本設置它們時,控制器將按照它應有的方向移動。爲了進行轉換,當剪輯到達結尾時,將轉換退出時間設置爲1.請記住,在轉換開始時,您仍然需要管理前端隊列數據結構並重置bools,阻止它到達下一個狀態並立即轉換到另一個狀態。

相反,您可以爲此設置自定義處理程序,它將設置當前正在播放的動畫。一個解釋

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

希望這會引導您朝着正確的方向前進。

+0

看來這對我來說有點太難了。它完美的工作,但我得到一個內存溢出:代碼:http://pastebin.com/bm3dqSHm PROFILER:http://imgur.com/a/dB2pl 尖峯發生後,我按下一個按鈕,並結束後動畫完成。動畫全部不循環,這就是43行應該是。它會被取消註釋,內存使用量會上升,直到發生溢出。這裏的背景究竟發生了什麼? – uncanny

+0

更新,當我只是用Play()而不用排隊啓動狀態時,這種行爲似乎更加明顯。一旦紋理被讀取,內存不會再次釋放,即使我再次啓動相同的狀態,它只是再次讀取它並分配兩倍的內存。 – uncanny

+0

不知道是什麼問題。我運行代碼並測試它,它工作正常。它沒有正確處理循環行爲,這對你來說是一個挑戰,但是代碼很好,並且不會產生垃圾。在播放模式打開時檢查您是否正在錄製,可能會導致問題。另一件事,要循環動畫,您需要在實際的動畫文件中檢查「循環時間」。 – JJC

0

您可以爲每個動畫腳本添加一個自定義變量。這些變量應該完全匹配您想要的順序。每個動畫結束時,爲該變量分配一個自定義值,並基於您剛分配的變量值開始下一個動畫腳本。

+0

順序是動態的(如,如果你推「平滑過渡到3」按鈕,它會等到當前動畫結束,然後開始動畫3),所以可以你解釋一下更詳細一點嗎?我不確定這是否對我在屏幕上的按鈕的「控制面板」有效,因爲每個按鈕都需要能夠訪問每個動畫的變量而不僅僅是控制器。 – uncanny