おもちゃラボ

Unityで遊びを作ってます

Unityでジニーエフェクト

Unityで小ネタアニメーション、第3回はジニーエフェクトを作ってみました。Macを使っている人には馴染み深いジニーエフェクトですね。あの、ウインドウがうにゅーーんってスケーリングするアレです。今回もUnity上で実装してみました。

作るもの

ジニーエフェクトではクリックした点に向けて、画像が縮小しながら吸い込まれていきます。もう一度画面上をクリックすると今度は拡大しながら、元の位置に戻ってきます。


- YouTube

ジニーエフェクトを作るにあたって、画像の頂点データを操作する必要があります。そんなローレイヤの値なんかUnityで触れるのかな、と思いきやMeshFilterを使えば簡単に取得できてしまいました。なので、今回はSpriteではなくPlainにMaterialとしてテクスチャを貼り付けています。

f:id:nn_hokuson:20140916211844j:plain

通常のPlainに貼り付けた場合は、上記の画像のように10x10のメッシュが自動的に生成されました。UnityのMeshFilterを自分で作成すれば、任意の解像度のメッシュが作れるようです。
http://www.atsuhiro-me.net/unity/dev/mesh

アルゴリズム

今回作成したジニーエフェクトのアルゴリズムですが、「各頂点に対してクリックされた位置からの距離に応じた速度を設定してやり、後は動かすだけ!」というなんとも簡単なアルゴリズムです。

縮小の場合のアルゴリズムは、下図のようにクリックされた座標(dst)から遠い頂点ほど、移動ベクトルが小さく(v3)、クリックされた座標から近いほど、移動ベクトルが大きくなっています。

f:id:nn_hokuson:20140916215653j:plain

拡張点座標に対して速度を設定する部分のプログラムは下記のようになっており、(1)タッチされた点を目標地点に設定し、(2)各頂点座標に対して、目標地点に向かう正規ベクトル(diff)を計算し、(3)その正規ベクトル対して距離で重みづけをしています。

for(int i = 0; i < m_vtxNum; ++i)
{
	m_vertices[i].dst  = touchPos;
	Vector3 diff 	   = (m_vertices[i].dst - m_vertices[i].src).normalized;
	m_vertices[i].v    = diff * SPEED  / (diff.magnitude);
}

今回は、目標点に向かう正規ベクトルを距離で割っているので、速度ベクトルは距離に反比例して大きくなります。グラフにするとこんなかんじですね〜。当たり前ですが、ゼロ距離だと速度ベクトルが無限大になるので注意してください。(ジニーエフェクトで拡大する場合に必要になります)

f:id:nn_hokuson:20140916220900j:plain

目標点に辿り着いたかどうかは、次のプログラムのように、移動開始座標から目標点に向かうベクトルと、現在座標から目標点に向かうベクトルの内積を計算して判定しています。単純に現在座標と目標点の距離を計算した場合、速度が早すぎてオーバーシュートする(すり抜ける)のを防ぐためです

if( Vector3.Dot( m_vertices[i].dst - m_tmpPos[i],  m_vertices[i].dst - m_vertices[i].src) < 0 )
{
    //到着!
}

ジニーエフェクトで拡大する場合は、ほとんど縮小する場合の逆の操作を行ってあげればOKです。つまり、出発点から遠い座標ほど早い速度ベクトルを設定し、出発点から近い座標ほど遅い速度ベクトルを設定してやります。各頂点座標の移動に関しては、イージングなどの処理を入れると、もっと綺麗に動くかもしれません。(動かないかもしれません笑)最後に、ジニーエフェクトを作成するのに使用したプログラムをおいておきます。参考にしてください。
Unityでジニーエフェクト

参考サイト

http://fladdict.net/blog/2009/09/flash-ginny-effect.html
http://wonderfl.net/c/qnTR


参考書籍