謹賀新年
結局年末年始の休暇を風邪で寝込んで過ごしたのに出社日には全快してしまった不運な皆さんこんにちは。今年の年末年始は例年よりもかなり寒かった為に大掃除で風邪を引いてそのまま正月を迎えました。おかげで予定したゲーム開発もほとんどできなかったのに、会社に向かう当日には治っているとか本当に不遇な子です。初詣で引いたお御籤は大吉だったのに。
一つの器に入れて混ぜないゲーム
以前からインディーゲーム紹介系のWeb記事でよく目にしていたものの、その紹介記事を幾ら読んでもゲーム内容が理解できず、それでも気になっていたゲームを購入しました。
遊べばすぐに理解できますがベルトアクション×リズムゲーム×同人なゲームです。従来のこういった複数ジャンルを掛け合わせたようなゲームって、それぞれのジャンルの要素をいい塩梅で融合させて一つのゲームとして形作るものが多いと思いますが、こちらのゲームは良い意味でベルトアクション、リズムゲーム、同人ゲームといった要素を一つの器に入れて混ぜない形になっています。
ベルトアクションパートでは敵に接近するとダンスという名の近接攻撃を行えますが、特にリズムに乗って操作するわけでなくコントローラーをガチャガチャすれば敵を倒せます。かと思えばボス戦で敵のHPを削ると自キャラとボスキャラが一緒にダンスし始め、急にリズムゲームが始まる、という仕様。リズムゲームをクリアすると同人ゲームっぽいピーキーな世界観の会話パートが始まり、またベルトアクションパートへと遷移していきます。
この手のコンテンツ特有の「お約束」が通じる方には刺さるゲームでしょうし、そうでない方には新しいゲーム体験として楽しめるゲームだと思います。
LitMotion ver.2.0
以前からUnityでオブジェクトの移動、回転、拡大等のTweenアニメーションを行うアセットとしてDOTweenが主流でしたが、最近ではJob SystemおよびBurst Compilerに対応して高速化を図ったアセットが色々と発表されていて、その中でもAnnulus Games氏が公開されているLitMotionはこのブログでも紹介させてもらいました。
LitMotionは既存のTween系アセットと比較してかなり高速であるという利点があるのですが、その分、DOTweenでは実装されているSequence(Tweenの連続再生)やPathに沿った移動などのメソッドは用意されていなかった為、DOTweenから移行する場合は使いどころ及び実装方法を事前に検討する必要があったのですが、このLitMotionが最近Ver2.0にアップデートされ機能面で大幅な強化が行われました。
Sequenceが使える
上のリンクを参照すると色々な機能が追加されているのが分かりますが、個人的に一番大きい変更点はSequenceが使える、という事でしょう。
SequenceはDOTweenなどでも頻繁に使用される機能で複数のモーションを順次実行したり、同時実行させたりする機能です。
例えば、以下のような車がA→B→Cの順に移動するような動作をさせたい場合、これまでは
- スタート地点からAへ移動するモーションを実行
- A→Bの移動モーションを実行
- B→Cの移動モーションを実行
という風に目的地が変わる毎にTweenモーションを実行するような実装が必要でした。
実際のコードはこんな感じ。ループ処理の中でawaitで一つの移動処理が終わるのを待って、移動先へ移動するモーションを実行させます(目的値の座標をリスト化している)
private async UniTaskVoid Start_SeqLitMotion(float moveTime) { // 経路単位にLitMotionを繰り返し実行 for (int iCnt = 0; iCnt < PosTranList.Count; iCnt++) { await LMotion.Create(TargetObj.transform.position, PosTranList[iCnt].transform.position, moveTime) .WithEase(Ease.Linear) .BindToPosition(TargetObj.transform); } }
これをLitMotionのver2.0ではDOTweenのSequcenceのように順次追加して行くことが可能となったので上のループ処理を強引に一文で書くと以下のような記述となります。
private async UniTaskVoid Start_SeqLitMotion(float moveTime) { await LSequence.Create() .Append(LMotion.Create(TargetObj.transform.position, PosTranList[0].transform.position, moveTime) .BindToPosition(TargetObj.transform)) .Append(LMotion.Create(PosTranList[0].transform.position, PosTranList[1].transform.position, moveTime) .BindToPosition(TargetObj.transform)) .Append(LMotion.Create(PosTranList[1].transform.position, PosTranList[2].transform.position, moveTime) .BindToPosition(TargetObj.transform)) .Run(); }
LSequence.Create()はインスタンスを変数として保持で来るので実際に実装する場合は、以下のようになるでしょうか。Sequenceの動作完了はWithCompleteのコールバックが用意されているのでそちらで検知しても良いですが、今回はawaitで一連の動作の完了を待っています。
private async UniTaskVoid Start_SeqLitMotion(float moveTime) { // Sequenceの編集 MotionSequenceBuilder seq = LSequence.Create(); Vector3 prevPos = TargetObj.transform.position; for (int iCnt = 0; iCnt < PosTranList.Count; iCnt++) { Vector3 purPos = PosTranList[iCnt].transform.position; seq.Append(LMotion.Create(prevPos, purPos, moveTime) .WithEase(Ease.Linear) .BindToPosition(TargetObj.transform)); prevPos = purPos; } // Sequenceの実行 await seq.Run(); }
最後に
これまでは機能が豊富なDOTweenと比較すると使い方に工夫が必要で利便性と高速化を天秤に掛けて使う必要があったのですが、今回のバージョンアップでかなり使いやすくなったのではないでしょうか?
現状DOTweenを使われている方でも移行を検討しても良いかと思います。。