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灯, 水草

请输入看板名称,例如:Boy-Girl站内搜寻

TOP