GameDesign 板


LINE

圖文版 http://goo.gl/bbpiJ 在製作遊戲的時候,動畫是不可或缺的一部份,即使是與遊戲核心無關的 GUI 部份,若少了動畫就顯得粗製濫造。然而大多數的 GUI 效果:像是視窗飛進 畫面中央、按下按鈕時放大效果之類的動畫等等,其內容都有很高的相似性, 也就是「在某段時間內,把物件的某些狀態轉移到另一個狀態」。若要使用 3D Max 之類的軟體一一製作,將顯得麻煩而沒有效率。 在這篇文章中,我會以 Unity 作為範例,介紹如何實作一個簡單的 easing function 元件。 範例需求 想像一下我們正在製作遊戲過程中的暫停選單。當玩家按下暫停鈕時,畫面上 會出現暫停的面板以及三個按鈕。當然,直接讓它們出現是很粗糙的作法,因 此我們希望面板及按鈕可以從畫面外飛進來。 使用線性內插 最簡單的呈現方式是使用線性內插法,指定好某個物件的起始狀態(位置、大 小、顏色等)與結束狀態,再指定動畫時間。只要有了這些資訊,我們可以用 簡單的數學運算內插出動畫播放時每一格 frame 的物件狀態。 using UnityEngine; using System; public class EasingDemo : MonoBehaviour { public Vector3 destination; public float duration = 1; public float delay = 0; private Vector3 source; private Vector3 delta; private float elapsed = 0; void Start() { source = transform.position; delta = destination - source; } void Update() { elapsed += Time.deltaTime; if(elapsed > delay && elapsed < (delay+duration)){ float ratio = Math.Min(1, (elapsed-delay)/duration); transform.position = source + ratio*delta; } } } 這個簡單的元件讓我們可以在 Unity 編輯器中直接設定物件的起始位置、結 束位置及動畫播放的時間。接下來,我們把面板與按鈕放在鏡頭外面,然後把 它的結束位置設定在畫面內,按下 play 後馬上可以看到它的效果……非常地 普通 XD http://youtu.be/h8KI88Tx_eQ
這個動畫之所以看起來很無聊,大部份的原因在於我們使用了很無聊的線性內 插法。想像一下如果這個按鈕是用以下的方式飛進畫面: * 很快地衝進來,然後緊急剎車停在目的地。 * 衝過頭然後拉回目的地。 * 撞到目的地後像皮球般反彈,最後再落回目的地。 這樣的動畫,顯然會比死板的等速度飛入更活潑、更有動感。然而製作這種動 畫效果就沒辦法用線性內插了。當然,若使用 3D Max 就可以藉由貝茲曲線 (Bézier curve) 來編輯這種較複雜的動畫,或是直接用 Unity 的動畫編輯器 也能辦到。然而編輯貝玆曲線的各個控制點卻是一件很花時間的工作,尤其像 第三個例子,為了達到反彈的效果,我們得額外加入兩三個 key frame 才行。 過程並不是很難,但就是很花時間。 使用 Unity 動畫編輯器的情況: http://goo.gl/RaEqu 使用非線性內插法 我們不希望動畫是平板的線性內插法,但又覺得編輯貝茲曲線的控制點太麻煩, 那麼答案就呼之欲出了:使用其它的數學曲線來代替直線。比如說如下的曲線: http://goo.gl/egaW6 儘管物理上並不正確,但它看起來就像是「很快地衝進來,然後緊急剎車」的 樣子。因此我們可以把它套用到內插計算式中: void Update() { elapsed += Time.deltaTime; if(elapsed > delay && elapsed < (delay+duration)){ float x = Math.Min(1, (elapsed-delay)/duration); float ratio = (float)Math.Pow(x-1, 3) + 1; transform.position = source + ratio*delta; } } 結果如下,同樣都是一秒鐘的動畫,感覺起來是不是有微妙的差異呢? http://youtu.be/UOIB7z220tw
Easing Function 慣例格式 Easing function 具有一項優勢:只要抽換不同的 easing function,不需要 另外編輯 key frame 或是曲線控制點,就馬上可以得到另一種動畫。但為了達 到這個「可抽換」的目的,我們得要使用大家所慣用的寫法: public class Easing { public static float Linear(float t, float b, float c, float d) { return c*(t/d) + b; } public static float OutCubic(float t, float b, float c, float d) { t /= d; t--; return c*(t*t*t+1)+b; } } 一般化的 easing function 有四個參數: * t (time): 代表動畫開始播放到現在所經過的時間。 * b (beginning): 代表某項屬性的初始值。 * c (change): 代表到動畫結束時,該屬性的變化值。亦即動畫結束後,這項屬 性的值應為 b+c。 * d (duration): 代表整段動畫的播放時間。 因此我們可以改寫原本的 Update(): public delegate float EasingFunction(float t, float b, float c, float d); EasingFunction easing = new EasingFunction(Easing.OutCubic); void Update() { elapsed += Time.deltaTime; if(elapsed > delay && elapsed < (delay+duration)){ Vector3 p = new Vector3(); float t = elapsed - delay; p.x = easing(t, source.x, delta.x, duration); p.y = easing(t, source.y, delta.y, duration); p.z = easing(t, source.z, delta.z, duration); transform.position = p; } } 這麼一來,我們就可以利用別人寫好的 easing function 套用到我們的動畫元 件中。事不遲疑,馬上就來看看範例。 彈跳動畫 上述「像是皮球般地彈跳」顯然是一種很困難的曲線,但早就有人寫好了它的 easing function,只要 google 一下馬上就能找到如下的程式碼: public static float Bounce(float t, float b, float c, float d) { if ((t /= d) < (1.0f / 2.75)) { return c * (7.5625f * t * t) + b; } else if (t < (2.0f / 2.75)) { return c * (7.5625f * (t-=(1.5f/2.75f)) * t + 0.75f) + b; } else if (t < (2.5f / 2.75)) { return c * (7.5625f * (t-=(2.25f/2.75f)) * t + 0.9375f) + b; } else { return c * (7.5625f * (t-=(2.625f/2.75f)) * t + 0.984375f) + b; } } 然後我們把 EasingDemo 中的 easing function 設定為 Easing.Bounce,馬上 就能看到彈跳的面板與按鈕: http://youtu.be/ZVZcXKFhGZw
這樣的效果是不是比前面慢慢飛進來的動畫要生動許多呢? 結語及參考資源 只要指定起始狀態、結束狀態、播放時間及 easing function 的種類,即可組合 出千變萬化的各種效果,因此 easing function 是相當廣泛的 2D 動畫技術。知 名的 JavaScript 函式庫 jQuery 也內建了許多不同種類的 easing function, 可以在 [http://goo.gl/zwkrq] 看到它們的效果。 Tim Groleau 的 easing function 產生器 [http://goo.gl/rpqFP] 則是一個幫 你產生程式碼的工具。你可以藉由拖拉控制點的方式編輯出你想要的曲線形式, 然後旁邊就會出現這個 easing function 的 JavaScript 程式碼。這個工具也事 先寫好了許多常用的 easing function 讓你可以直接利用。 最後,這篇教學的 Unity 範例場景可以在 [http://goo.gl/Xq9e5] 下載。只要 開一個新的 Unity 專案並選擇匯入套件,即可看到範例程式碼及實際的動畫效果。 --



※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 202.39.238.241
1F:推 Transformers:推 分享 09/16 21:50
2F:推 a83a83cjcj:實用推 09/16 22:25
3F:推 tsl3333:推!!! 09/16 22:55







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:Tech_Job站內搜尋

TOP