2012年4月1日 星期日

自訂動畫節點

UE的動畫樹(AnimTree)提供動畫混合、變形混合、骨架控制三種功能。它可以讓開發者自訂節點來擴充新的功能,在此篇簡單說明一下如何自訂動畫節點。

動畫節點的基礎類別叫做AnimNode,其他的動畫節點都會直接或間接繼承自此類別。它的子類別主要可分為:
  • 代表動畫的葉節點
  • 混合子節點動畫的中間節點
前者通常繼承AnimNodeSequence類別而來
後者通常繼承AnimNodeBlendBase類別(或其子孫)而來

AnimNode類別體系

AnimNode以C++虛擬函式的方式供子類別覆載自訂行為,以下列出重要的擴充函式:
  • InitAnim( SkeletalMeshComponent, ParentNode ):當SkeletalMeshComponent初始化其AnimTree時會呼叫此函式。第二個參數雖說是父節點,實際上執行時是傳入NULL。
  • TickAnim(DeltaSeconds):可覆寫此函式更新節點。
  • GetBoneAtoms(OutAtoms, Bones, OutRootMotionDelta, bOutHasRootMotion, ...):取得目前骨架位置,以及上個frame到目前frame之間root motion偏移量。如果有子節點,則是子樹中所有作用中的節點混合而成的結果。
  • PlayAnim(bLoop, Rate, StartTime):播放動畫。
  • StopAnim():停止動畫。 
  • OnBecomeRelevant():當此節點的權重變成大於零時會呼叫此函式。 
  • OnCeaseRelevant():當此節點的權重變成零時會呼叫此函式。

每個SkeletalMeshComponent會複製一份專用的動畫樹,所以即使許多模型使用同一個動畫樹範本,像是目前動畫時間這種每個實例都要另記一份的資料,還是可以直接存放在動畫節點上。大部分動畫節點的功能是由C++實作,所以沒有原始碼授權的UDK使用者很難去擴充節點。

範例


原本AnimNodeSequence沒有在編輯器勾選bPlaying欄位的話,會需要由父節點啟動播放。以下程式碼展示如何自訂一個會在節點啟動時自動播放的動畫節點:
class MyAnimNodeSequence extends AnimNodeSequence;

var() bool bAutoStart;

event OnBecomeRelevant()
{
    if( bAudoStart && ! bPlaying )
    {
        ReplayAnim();
    }
}

defaultproperties
{
    bCallScriptEventOnBecomeRelevant=true
}
上面的程式碼完全用UnrealScript實作,效能較差,以下提供另一個用C++實作的版本:
class MyAnimNodeSequence extends AnimNodeSequence
    native(Anim);

var() bool bAutoStart;

cpptext
{
    // AnimNode interface
    virtual void OnBecomeRelevant()
    {
        if( bAudoStart && ! bPlaying )
        {
            ReplayAnim();
        }
    }
}

沒有留言:

張貼留言