読者です 読者をやめる 読者になる 読者になる

おもちゃラボ

Unityで遊びを作っていきます

Unityでジニーエフェクト

Unity

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

作るもの

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


Unityでジニーエフェクト - YouTube

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

f:id:nn_hokuson:20140916211844j:plain

通常のPlainに貼り付けた場合は、上記の画像のように10x10のメッシュが自動的に生成されました。UnityのMeshFilterを自分で作成すれば、任意の解像度のメッシュが作れるようです。
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でジニーエフェクト

参考サイト

Flashでジニーエフェクト | fladdict
Ginny Effect Modoki - wonderfl build flash online


参考書籍

Flash Math Creativity

Flash Math Creativity

ActionScript 3.0 アニメーション

ActionScript 3.0 アニメーション