作者littleshan (我要加入剑道社!)
看板GameDesign
标题[程式] 使用 Easing Function 编辑动画
时间Sun Sep 16 16:39:57 2012
图文版
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