以下の内容はhttps://www.karvan1230.com/entry/2025/07/01/200000より取得しました。


【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;
  })

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

 

最後に

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

 




以上の内容はhttps://www.karvan1230.com/entry/2025/07/01/200000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14