2016年4月5日火曜日

UnityアセットのHOTweenでループ使おうとしたらなんかアホみたいなコードになった

最近HOTweenを使うことがちょいちょいあるので備忘録がてらメモ。ググっても全然情報出てこないしな…。
てかぶっちゃけこれそんな使いやすいわけでもない。
NGUIの付属ライブラリでいいよもう(?)

ちなみにTweenとは

Twitter用のクライアントアプリのことではないです。一応。
2点間のアニメーションを補間してくれる奴のことを指します。
他ではどうかしらないけど、Unity界隈ではツイーントゥイーン言いまくってて標準用語化してます。

例えば、ゲームでダイアログがポップアップするやつはスケールをTweenしているし、
キャラクターが徐々に透明になってフェードアウトしていくやつはアルファ値( Color)をTweenしていて、
画面外からスーッとUIが移動してくるやつは座標をTweenしています。
パッと消える・パッと現れる、という風な雑な表示にならないので、とても目に優しいです。

目に優しいというか、これが今のゲームの標準クオリティ・やってて当たり前みたいなとこがあるので、やらないと逆に?な評価をされかねないです。
至る所で一手間加えないといけない上に、補間の仕方をしくじると違和感丸出しになるんで地味に面倒いですが。

なので今後Tweenしていない上になんか表示が雑なUIのゲームがあったら、
「これUIアニメーションの補間が全然なってない。クソゲ。」
とドヤ顔で言いふらしてやりましょう(やめて下さい心が傷むので)。



類似ライブラリ一覧

そんなわけで頻繁に利用する機会のある機能なので、Unityで便利に使えるライブラリやらなんやらがアセットとしていくつか存在しています(こんなのを一から実装するのは学生か、なんでも自作じゃないと気が済まないキチガイだけです)。
以下適当に触れていきます。

【NGUI Tween】…大人気UIアセットにくっついてくるやつ。複雑なことはやりにくい印象はあるものの、コードを書かずともコンポーネントを貼り付けてちゃちゃっと簡単な補間を済ませることができるので便利。
定常ループとか生成時に一度きりの固定アニメーションとかやらせたいとき(Animatorセットするのがめんどい気分の時)にたまに使う。

【iTween】…多分一番人気のアセット。検索するとこればかり出てくる。Tweenやりたかったらこれでいいと思う。ちなみに使ったことないので特に触れない。

【DOTween】…HOTweenのver2的な立ち位置らしい。じゃあHOTweenいらないじゃん。なんなの。

【HOTween】…今回触れるアセット。「HOTween ループ」でググると、もしかして: ITween ループ、って出てくる。ホントに使ってるやついんのかこれ。



んじゃあ適当紹介終わったので早速実例を見ていきます。



うんこコード実演



Tweener tweener;
private void PlayTween(Vector3 begin, Vector3 end)
   {
       if(tweener != null)  tweener.Kill(); // 多重再生を防止

       transform.position = begin;
       ResetAnimation(); // 定常アニメーションをリセットする関数
       tweener = HOTween.To (transform, 1.0f, new TweenParms ()
                              .Prop ("position", end, false)
                              .Ease (EaseType.EaseOutStrong)
                              .OnComplete(() => { PlayTween(begin, end); })
                              .Delay(0.5f));
                      //       .Loops(-1, LoopType.Restart));
   }


以下解説。
・HOTweenクラスの静的メソッドであるTo()を呼び出すことによってTweenオブジェクトが生成され(GameObjectです)、補完が開始される。
・第一引数にはTweenをかけたい対象ならなんでも、第二引数は補間開始から終了までの時間(例だと1秒)、第三引数にパラメータを色々設定できる。
・Prop()は順に「プロパティ名」「補間終点値」「現在値に加算していくかどうか」といった感じ。この場合だと、「transform」の「position」プロパティの値を、1秒の間、beginからendに徐々へと近づけていくことになる。
・Ease()は補間の種類を選ぶ。EaseTypeとかいうenum値から色々お好みで。
・OnComplete()は補完終了時に呼ばれるコールバックを指定できる。上図だと再帰っぽく呼び出してやってループをアニメーションのループを実現している。
・Delay()は補完開始するまでの待機時間を指定できる。例だと0.5秒。
・(コメントアウトしてるけど)Loops()でループアニメーションが可能。第一引数に-1で永久ループ、第二引数でループの種類を指定。ちなみにこれデフォルト引数が1になっていて、そのままだと1再生のみ(1回ループ扱い)になる。
(この時点でクソ。なぜ-1をデフォルトにしなかったのか謎すぎる。)
※他にも色々パラメータ指定できる。けどよく知らないので割愛。


上記例はLoopsでループ指定できるのにも関わらず、わざわざコールバックで再度同じメソッドを呼び出してやることでループ処理を実装している。
なぜこんな面倒なことをやっているかというと、
①Delayが初回の補完開始時にしか反映されない。
 →毎回delayして欲しいのに二回目以降は待機してくれない。今思うと、Tweenerインスタンスのプロパティにもしかしたらdelay関連の変数を操作できるものがあるかもしれないけど、最初からパラメータ設定するときに指定できるようになってないHOTWeenはクソ。
②OnCompleteのコールバックがループ指定されてると呼ばれない。
 → そのせいで、ループの度にやらせたい処理(ResetAnimation()とか)が、コールバックに書いただけでは走らない。一応、OnStepComplete()なるものがあるので、こっちなら呼ばれるかも?いずれにせよわかりづらいしオプションで指定できるようになってないHOTWeenは以下略。OnCompleteへ渡すコールバックに、ループ中のものか判定するbool型引数持たせればいいだけじゃね?せめてサマリーで注意書きでも書いといてくれたらねえ。



いまいちピンと来ねえのは俺のスキルがアレだからですかそうですか

でもUnityの思想はゲーム開発の民主化じゃん?みんながみんなプログラム自信ニキって市場じゃないし、頻繁に使う機能なんだからできるだけわかりやすくして欲しいね、俺はそう思うよ。

ということで愚痴言って終わり。

0 件のコメント:

コメントを投稿