Animation 組件

Animation概述

Animation 組件,Animation類

Animation

//測試的結果是:
//1、特別注意 XXQueue 這樣的函數,如果遇到循環播放的動畫 WrapMode.Loop ,
因爲默認情況 QueueMode.CompleteOthers,所以無法切換到其他動畫
//2、如果將動畫隊列模式設爲 QueueMode.PlayNow,那麼即使是 循環播放的動畫,它也會自身切換自身,從頭開始播放
//3、文檔中的 Animation.CrossFadeQueue

https://docs.unity3d.com/ScriptReference/Animation.CrossFadeQueued.html


PlayMode 用於動畫的播放相關函數,影響其他動畫的播放,可以停止同一層、所有層的其他動畫

PlayMode.StopSameLayer —— 針對同一層的其他動畫(停止、淡出)(這種其他層的動畫還可以繼續播放)
PlayMode.StopAll —— 針對所有其他動畫(停止、淡出)

已經過時的 API 還有一個 AnimationPlayMode ,如今用 PlayMode 代替。
然而,AnimationPlayMode 枚舉有三項: Mix、Queue、Stop


public class Animation : Behaviour{}

另外需要關注 —— AnimationState、AnimationClip、

動畫系統基於權重,支持 動畫混合(blending),添加動畫(additive animations),動畫融合(mixing),層,以及其他動畫播放的控制。

AnimationState 用於切換動畫的層,控制播放速度,以及對blending和mixing的直接控制。

Animation 支持枚舉器,所以可以寫代碼如下

public class Example : MonoBehaviour
{
    public Animation anim;   //例子中也從沒有出現 Animator、以及動畫狀態機的概念

    void Start()
    {
        anim = GetComponent<Animation>();
        foreach(AnimationState state in anim)  //看來這個 AnimationState 在舊版本就有了。。。
            state.speed = 0.5f;
    }
}

Animation 屬性

Animation 屬性名 說明
animatePhysics 如果設爲true,那麼動畫將會在 FixedUpdate 中循環,這個只有和運動學剛體一起用纔有效(bool)
clip 默認的動畫片段 (AnimationClip)
cullingType 控制這個Animation組件的 (AnimationCullingType)
isPlaying 這個組件是否正在播放動畫,動畫播放結束不動了,那也是false (注意還有個 anim.IsPlaying(“xx”))(bool)
localBounds AABB of this Animation animation component in local space.(Bounds)???
playAutomatically 默認的動畫片段是否自動播放(bool)
this[string] 返回某個名稱的動畫狀態,例如 anim[“walk”] .(AnimationState)
wrapMode 循環播放設置,建議是在導入設置中對每一個動畫片段的WrapMode單獨處理好(WrapMode)

關於 WrapMode
推薦這樣用:先在導入設置中設置每一個動畫片段的WrapMode,當一個 AnimationState 被創建,它就會有用到的 AnimationClip 的 WrapMode 信息,並且也是可以通過程序來改變的。
如果一個AnimationState的 WrapMode 設爲 Default,那麼動畫系統將會使用 Animation組件的 WrapMode。
.
意思應該就是說,
AnimationClip 的 WrapMode 最先考慮,AnimationState被創建的時候就會用到 AnimationClip的 WrapMode,但是也可以改變。如果 AnimationState 的 WrapMode 爲默認,那麼就會用到 Animation組件的設置

.

關於 AnimationCullingType,
.
即使邏輯和動畫表現分離,也不能隨便用,例如一個怪的動畫裏邊有 後撤+突進+攻擊,後撤的時候離開屏幕,接着就不會突進了,處理起來還更麻煩
.
AlwaysAnimate 、 BasedOnRenderers
.
When culling is enabled, Unity might stop animating if it thinks that the results of the animation won’t be visible to the user. This could save you some performance if you have things animating outside of the viewport, whose animation is only important when the user can actually see the thing that is being animated. When Animation component is culled it won’t do anything: it won’t update animation states, execute events or sample animations.

Animation 公共方法

Animation 公共方法 說明
AddClip 給Animation組件添加新動畫片段,指定源動畫,新名稱,如果名稱與已有的相同,那麼會取代
Blend 將某個名稱的動畫片段在 幾秒內(默認0.3秒),改變權重到目標權重(默認1)。。fadeLength 應該是時間吧。。
CrossFade 在指定時間內(默認0.3s),指定動畫的淡入,其他動畫的淡出(同一層/所有)
CrossFadeQueued 動畫的淡入淡出,特別注意 QueueMode 的設置,默認播放完其他動畫才cross fade,然而如果循環播放,那麼就相當於動畫不會停止,所以也就不會 cross fade。然後如果設置爲 QueueMode.PlayNow ,那麼還可以自身cross fade到自身(似乎是unity內部會複製一份的意思)
GetClipCount 獲取這個Animation組件的動畫片段數量
isPlaying 是否正在播放某個動畫
Play 播放指定動畫,沒有任何混合
PlayQueued 一般 QueueMode.CompleteOthers 等其他動畫播完再播指定動畫,沒有淡入淡出,同樣注意 循環播放的動畫切換到指定動畫,必須 QueueMode.PlayNow
RemoveClip 從Animation組件的動畫列表中移除指定動畫片段,以及基於此動畫片段的動畫狀態
Rewind 就是將動畫從頭開始播放,不管是不是循環播放的,另外注意如果動畫播放結束再執行 Rewind 是無效的
Sample 應該是設置好一個動畫狀態,然後採用一次,效果貌似是那個動畫狀態的參數應用到其他動畫狀態?????
Stop 可以停止指定動畫,也可以停止該組件所有動畫,注意Stop的同時也就Rewind到開始,“凍結”效果,anim.isPlaying ==false
//給組件添加新的動畫片段,指定源動畫片段實例,新動畫片段的名稱,這種是不會保存到FBX裏邊的,只會運行時有效
public void AddClip(AnimationClip clip, string newName); 
//這個也是給組件添加新的動畫片段,並且指定新片段的名稱、第一幀、結束幀取自源動畫片段的哪一幀,是否開始和結束循環
public void AddClip(AnimationClip clip, string newName, int firstFrame, int lastFrame, bool addLoopFrame = false); 
//將指定名稱的動畫片段,過渡到指定的權重,fadeLength 是時間???
public void Blend(string animation, float targetWeight = 1.0F, float fadeLength = 0.3F); 
public void CrossFade(string animation,                 //目標動畫名稱
                      float fadeLength = 0.3F,          //時間,默認0.3s
                      PlayMode mode = PlayMode.StopSameLayer);   //默認是同個layer的動畫 fade out

//PlayMode 用於 Animation.Play  Animation.CrossFade  決定處理的是同一層的動畫還是所有動畫
//PlayMode.StopSameLayer —— 針對同一層的動畫(停止、淡出)(這種其他層的動畫還可以繼續播放)
//PlayMode.StopAll —— 針對所有動畫(停止、淡出)
//在上一個動畫播放結束之後cross fade到目標動畫,就像是一個動畫播放的隊列

//string animation —— 目標動畫名稱
//float fadeLenght —— 時間 默認0.3s
//QueueMode queue —— 隊列模式 默認QueueMode.CompleteOthers , QueueMode.PlayNow
//PlayMode mode —— 播放模式,默認停止同一層

public AnimationState CrossFadeQueued(string animation, 
                                      float fadeLength = 0.3F, 
                                      QueueMode queue = QueueMode.CompleteOthers, 
                                      PlayMode mode = PlayMode.StopSameLayer); 


//測試的結果是:
//1、特別注意 XXQueue 這樣的函數,如果遇到循環播放的動畫 WrapMode.Loop ,因爲默認情況 QueueMode.CompleteOthers,所以無法切換到其他動畫
//2、如果將動畫隊列模式設爲 QueueMode.PlayNow,那麼即使是 循環播放的動畫,它也會自身切換自身,從頭開始播放
//3、文檔中的 Animation.CrossFadeQueue 沒咋看明白

https://docs.unity3d.com/ScriptReference/Animation.CrossFadeQueued.html

public int GetClipCount();
public bool IsPlaying(string name); 
//播放默認的動畫,如果沒有默認動畫,那麼返回false
public bool Play(PlayMode mode = PlayMode.StopSameLayer);
//播放指定動畫,PlayMode 影響其他層或所有層的 其他動畫的播放
public bool Play(string animation, PlayMode mode = PlayMode.StopSameLayer); 

如果指定的動畫已經正在播放,那麼再執行這個 anim.Play("xx"); 不會導致回退到動畫開始。
動畫播放結束,除非是 WrapMode.Loop 那麼動畫就停在那了,模型也就一個pose,並且 anim.isPlaying == false
//和 CrossFadeQueue 類似,但是這個沒有混合

public AnimationState PlayQueued(string animation, 
                                 QueueMode queue = QueueMode.CompleteOthers,
                                 PlayMode mode = PlayMode.StopSameLayer); 
public void RemoveClip(AnimationClip clip); 
public void RemoveClip(string clipName); 
//就是將動畫從頭開始播放,不管是不是循環播放的,另外注意如果動畫播放結束再執行 Rewind 是無效的

public void Rewind(string name);    //指定某個動畫從頭開始播放
public void Rewind();    //全部動畫都從頭開始播放(可以有多個層的動畫)
//貌似是先設置一個動畫狀態,然後 anim.Sample(); 採樣一次,似乎是將這些參數應用到其他動畫狀態???

public void Sample(); 

//Samples animations at the current state.
//This is useful when you explicitly want to set up some animation state, and sample it once.


public class ExampleClass : MonoBehaviour {
    public Animation anim;
    void Start() {
        anim = GetComponent<Animation>();
        anim["MyClip"].time = 2.0F;
        anim["MyClip"].enabled = true;
        anim["MyClip"].weight = 1;
        anim.Sample();
        anim["MyClip"].enabled = false;
    }
}
public void Stop(); 
public void Stop(string name); 

最後貼上代碼

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum ESelectedFunc
{ 
    Play,
    PlayQueue,
    CrossFade,
    CrossFadeQueue
}

public class TestPlayAnimation : MonoBehaviour {

    Animation anim;

    int animChangeModeSelected =0;
    int playModeSelected = 0;
    int queueModeSelected = 0;
  //  int animPlayModeSelected = 0;

    string[] animationNames = { "free", "walk", "attack" };

    string[] animChangeToolbar = { "Play", "PlayQueue", "CrossFade", "CrossFadeQueue" };
    string[] playModeToolbar = { "StopSameLayer", "StopAll" };
    string[] queueModeToolbar = { "CompleteOthers", "PlayNow" };

  //  string[] animationPlayModeToolbar = { "Mix", "Queue", "Stop" };


    void Start () 
    {
        anim = GetComponent<Animation>();
    }

    void OnGUI()
    {
        GUI.Label(new Rect(100, 50, 100, 50), "FunctionName");
        animChangeModeSelected = GUI.Toolbar(new Rect(200f, 50f, 500f, 50f), animChangeModeSelected, animChangeToolbar);

        GUI.Label(new Rect(100,110,100,50),"PlayMode");
        playModeSelected = GUI.Toolbar(new Rect(200, 110, 240, 50), playModeSelected, playModeToolbar);

        GUI.Label(new Rect(100, 170, 100, 50), "QueueMode");
        queueModeSelected = GUI.Toolbar(new Rect(200, 170, 240, 50), queueModeSelected, queueModeToolbar);

        //GUI.Label(new Rect(100, 260, 100, 50), "AnimationPlayMode");
        //animPlayModeSelected = GUI.Toolbar(new Rect(200, 260, 300, 50), animPlayModeSelected, animationPlayModeToolbar);

        OtherGUI();

        ProcessAnimation();
    }


    void OtherGUI()
    {
        GUI.Label(new Rect(100, Screen.height - 100, 200, 50), "anim.isPlaying :   " + anim.isPlaying);

        if (GUI.Button(new Rect(Screen.width - 220, Screen.height - 100, 100, 50), "Rewind"))
        {
            anim.Rewind();
        }
        if (GUI.Button(new Rect(Screen.width - 110, Screen.height - 100, 100, 50), "Stop"))
        {
            anim.Stop();
        }
    }

    void ProcessAnimation()
    {
          ESelectedFunc mode = (ESelectedFunc)animChangeModeSelected;

        foreach (string str in animationNames)
        {
            if (GUILayout.Button(str))
            { 
                switch(mode)
                {
                    case ESelectedFunc.Play:
                        anim.Play(str,(PlayMode)playModeSelected);
                        break;
                    case ESelectedFunc.PlayQueue:
                        anim.PlayQueued(str,(QueueMode)queueModeSelected,(PlayMode)playModeSelected);
                        break;
                    case ESelectedFunc.CrossFade:
                        anim.CrossFade(str,0.3f,(PlayMode)playModeSelected);
                        break;
                    case ESelectedFunc.CrossFadeQueue:
                        anim.CrossFadeQueued(str,0.3f,(QueueMode)queueModeSelected,(PlayMode)playModeSelected);
                        break;
                    default:
                        break;
                }
            }

        }
    }


}
發佈了46 篇原創文章 · 獲贊 8 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章