原カバンは鞄のお店ではありません。

Unityを使ったゲーム制作のあれこれを綴っていきます。

【Unity】2次ベジェ曲線を使ってLitMotionでジャンプ機能を実装する

夏風邪

先週発症した夏風邪が一週間たっても未だ完治しない虚弱体質な皆さんこんにちは。発熱や鼻水等の症状は収まったのですがずっと咳が止まりません。咳止めを飲んでも完全に収まらず、咳をすると頭と胸に響いて痛いです、助けて。

 

LitMotion

Unityで標準的に使用されているTween系アセット言えばDoTween辺りが上げられそうですが、ここ最近ではLitMotionも広く使われるようになってきていると思います。

github.com

LitMotionは有志の方によって作成されたたフリーライブラリでDoTweenを比較して機能数では劣るもののTween処理が5倍ほど高速であることが最大の特徴なんですが、少し前のバージョンアップにより、PunchやShakeといったAPIと共にSequence(複数Tweenの順次実行)の機能が追加され、以前と比べてかなり使い勝手の良いライブラリになったと思います。

とは言え、DoTweenには実装されているのにLitMotionでは実装されていない機能が未だあるのは事実で、個人的にはJump系のTween機能がLitMotionに実装されていないのはちょっと痛い。DOPathのようなPathに沿った移動の機能も無いんですが、そちらはSplineを利用することで実装することができたので、以前このブログの記事で紹介しました。

www.karvan1230.com

 

その場でのジャンプ

Jump系機能が無いのは痛いとはいうものの、場所を移動せずに上方向にだけ飛びあるような動作の場合はジャンプの始点から最高到達点までの移動に対して、Easingに放物線を描くカーブを指定すればそれっぽい動作になるので、特に何か難しい工夫をする必要はありません。

Easingにこんな感じのAnimationCurveを指定

 

場所が変わらないその場でのジャンプ動作

 

問題はジャンプしつつ他の場所に移動するようなケースで、例えば下の図のような場面

ペンギンがジャンプして正面にあるCUBEの上面に乗る動作を作りたい場合、Easingの指定だけでは放物線を描いて移動するようなジャンプ動作は作れません。

 

2次ベジェ曲線を使おう

オブジェクトが放物線を描いて移動するには、その放物線を計算する必要がありますが、わざわざ放物線の方程式を書いて計算するよりベジェ曲線を使った方が簡単だと思います。
ベジェ曲線とはコンピュータ上で滑らかな曲線を表現するための計算手法で、始点と終点の間にN個の制御点を設けてそれらを利用して曲線を描きます。より複雑な曲線を描こうとすると制御点の数を増やしていく必要がありますが、今回は簡単な放物線の為、制御点を1個設ける「2次ベジェ曲線」を使う事とします。

 

先ほどの説明だと難しそうな処理になりそうな印象ですが、以外にも2次ベジェ曲線の計算は以下の3ステップで計算することが可能です。

  1. 始点と制御点を結ぶ直線上の点を計算する
  2. 制御点と終点を結ぶ直線上の点を計算する
  3. 1の点と2の点を結ぶ直線上の点を計算する

上の3ステップで導き出した3ステップ目の点が2次ベジェ曲線を描く点となります。1~3の点を時間と共にそれぞれの直線上で移動させてやると2次ベジェ曲線が描かれます。具体的には下の動画の白い曲線が2次ベジェ曲線となります。

 

実装しよう

上記の1~3の点はVector3のLerpを使えば簡単に求められます。

Vector3 CalBezierCurve(Vector3 start, Vector3 end, Vector3 control, float t)
{
  // ①.始点と制御点を結ぶ直線を移動する
  Vector3 Q0 = Vector3.Lerp(start, control, t);
  
  // ②.制御点と終点を結ぶ直線を移動する
  Vector3 Q1 = Vector3.Lerp(control, end, t);
  
  // ③.①と②を結ぶ直線を移動する
  Vector3 Q2 = Vector3.Lerp(Q0, Q1, t);
  
  retur Q2;
}

 

上の関数に渡すtの値をLitMotionにより0~1に変化させて逐次オブジェクトのポジションに反映されてあげれば放物線を描きながらの移動が可能となります。

LMotion.Create(0.0f, 1.0f, moveTime)
  .WithEase(Ease.Linear)
  .Bind(value =>
  {
    Vector3 modPos = CalBezierCurve(StartPos, EndPos, ControlPos, value);
    this.transform.position = modPos;
  })

実際にはこんな感じの動作となります。

 

最後に

ベジェ曲線の性質上、制御点は放物線の最高到達点ではないので、最高到達点を指定するような放物線は描けないのですが。でも複雑な計算式を必要としない、それとなく放物線を描いているように見せたい場合にはこれで十分な気もします。

 

◇プライバシーポリシー

●個人情報の利用目的

当ブログでは、メールでのお問い合わせ、メールマガジンへの登録などの際に、名前(ハンドルネーム)、メールアドレス等の個人情報をご登録いただく場合がございます。

これらの個人情報は質問に対する回答や必要な情報を電子メールなどをでご連絡する場合に利用させていただくものであり、個人情報をご提供いただく際の目的以外では利用いたしません。

●個人情報の第三者への開示

当サイトでは、個人情報は適切に管理し、以下に該当する場合を除いて第三者に開示することはありません。

・本人のご了解がある場合
・法令等への協力のため、開示が必要となる場合

個人情報の開示、訂正、追加、削除、利用停止
ご本人からの個人データの開示、訂正、追加、削除、利用停止のご希望の場合には、ご本人であることを確認させていただいた上、速やかに対応させていただきます。

アクセス解析ツールについて

当サイトでは、Googleによるアクセス解析ツール「Googleアナリティクス」を利用しています。

このGoogleアナリティクスはトラフィックデータの収集のためにCookieを使用しています。このトラフィックデータは匿名で収集されており、個人を特定するものではありません。
この機能はCookieを無効にすることで収集を拒否することが出来ますので、お使いのブラウザの設定をご確認ください。

●免責事項

当サイトからリンクやバナーなどによって他のサイトに移動された場合、移動先サイトで提供される情報、サービス等について一切の責任を負いません。

当サイトのコンテンツ・情報につきまして、可能な限り正確な情報を掲載するよう努めておりますが、誤情報が入り込んだり、情報が古くなっていることもございます。

当サイトに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。

●プライバシーポリシーの変更について

当サイトは、個人情報に関して適用される日本の法令を遵守するとともに、本ポリシーの内容を適宜見直しその改善に努めます。

修正された最新のプライバシーポリシーは常に本ページにて開示されます。