關於 web service, unity, blogger 等軟體工程筆記

Unity Platformer 2D: Character Animations

Edit icon 沒有留言
Unity

延續上一篇 Character 2D Movement using Physical in Unity 的練習,繼續使用 FGJ 活動中,團隊所繪製的素材繼續練習。這次要結合之前的角色移動以及跳躍功能,加上播放對應的動畫。

Prepare Animation Clips

製作人物動畫,這次美術並不是繪製完每個 frame 所有的貼圖,沒法用 sprite animations 方式來製作人物動畫。美術一共輸出五張貼圖,分別為左右腳,左右手以及身體,要用這些貼圖在 Unity 中來組合出人物動畫。

拿以前 3D 建骨骼 (Bones) 的概念來套用,建立其 GameObject hierarchy 的架構,如下圖示意圖。root 為角色骨盆位置,上半身 body & 左右腳left-leg & right-leg 連接在 root 上 (as transform children)。左右手 right-hand & left-hand 則是連接著 body。

物件架構示意圖

人物架構示意圖,紅色為 GameObject pivot 位置,綠色為 Sprite renderer 的示意

動畫片段 (Animation Clips) 的製作,對於非美術,不常使用 Unity Animation 工具建立動畫的人來說,就是某種苦工了。使用 Animation 工具在 Editor 中編輯動態,中途還遇到動態不正常的 Bugs,還因而重做幾次 Clips,直到找到 Bugs 修正動畫為止…。動畫還是交給比較有 Sense 的美術去建立吧。

完成三組動畫,分別是待機 (Idle),走路 (Walk) 以及降落 (Landing),這些動畫不包含位移 (Translation) 資料,僅僅在原地演出動作。

待機

待機

走路

走路

降落

降落

關於編輯中遇到的動畫 Bugs,主因在 Landing 動畫沒法正常讓其中一隻手旋轉,可在 Editor 預覽播放是正常的,當進入到 Play Mode 後,就沒有辦法正常播放 Landing 的動態,

最後該問題的解決方法是,將所有 Clips 中的 rotation interpolation 方式,全部改成相同,不要有混和的方式。當內插方式全部設定為 Euler Angles (Quaternion Angles) 後,就一切正常了。想想可能是遇到 Gimbal lock 鎖死導致不能旋轉的問題。

旋轉內插方式設定

設定旋轉的內插方式

Create Animator Controller

根據需求建立 States,建立三個 Animation States,分別是 Idle, Walk, and Landing,對應使用上節製作的 Clips。參數設定有 Walk, Grounded and Speed 三個參數。

  • Walk: 用來切換 Idle & Walk State,當 Walk = true,從 Idle 切換到 Walk。反之從 Walk 切換到 Idle。至於 Transition 參數就按照動畫表現,慢慢去調整了。
  • Grounded: 判斷目前是否在地面上。當 Grounded = false,從任意 State 切換到 Landing,但不可以從 Landing 切到 Landing (Can transition to self = false)。當 Grounded = true 時,便從 Landing 切換到 Exit state,回到 Initial state (Idle)。
  • Speed: 控制走路動畫播放速度,作為 Walk state 的速度加成 (Multiplier)。程式設定此值會是正規化成 [0-1] 的數值,以方便後續調整其動畫速度。
Animator Controller

Animator Controller

Modify Code

修改 PlayerMoveController 內的程式碼,加上設定 Animator 參數的程式:

void Update()
{
var speed = Mathf.Abs(this.GetComponent<Rigidbody2D>().velocity.x);
var gounded = this.GetComponent<GroundDetector>().Grounded;

// ... 省略 Jump 控制 ...

var anim = this.GetComponent<Animator>();
anim.SetBool("Grounded", gounded);
anim.SetBool("Walk", speed > 0);
anim.SetFloat("Speed", Mathf.InverseLerp(0, this.MaxSpeed, speed));
}

每次 Update 設定是否在地上的判斷,使用目前的速度 > 0 來判斷是否移動中,最後設定 Speed 以最大速度 normalized [0-1] 的數值。

就這麼少程式碼修改就完成了動畫控制,動畫最麻煩應該是前置的 Clips 製作,以後還是交給專業的美術來好了。

成果展示

成果展示

完整練習範例放置在 Github,week2。

Github

Series

Reference

沒有留言: