私が解決しようとしている問題は、一定の速度で 3 次ベジエ曲線に沿って 2D ポイントを移動できないように見えることです。
私はこのチュートリアルに従いました: http://catlikecoding.com/unity/tutorials/curves-and-splines/最初に曲線を実装すると、素晴らしく機能しました。しかし、一定の速度でポイントを近似しようとすると、かなり外れます。
私がこれまでに読んだことから、各ステップ時間で弧の長さと間隔の距離を計算して、曲線を反復処理することになっています。次に、これらの距離を目標距離 (弧の長さ * 時間) と比較して、最も近い距離を見つけます。解像度が十分に高い場合、これはエラーがほとんどなく、私のニーズに対して十分に正確であるはずです。
これが私がこれまでに持っているコードです:
ポイント計算:
public static Vector3 GetPoint (Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
{
t = Mathf.Clamp01(t);
float oneMinusT = 1f - t;
return
oneMinusT * oneMinusT * oneMinusT * p0 +
3f * oneMinusT * oneMinusT * t * p1 +
3f * oneMinusT * t * t * p2 +
t * t * t * p3;
}
一定時間でポイントを計算するという悲しい試み:
private float GetApproximatedTime(float u)
{
int resolution = 100;
float ratio = 1.0f / resolution;
float arcLength = 0.0f;
Vector3 p0 = SelectedSpline.Evaluate(0.0f);
List<MultiCurveUtility.ArcTimeLength> arcTimeLengthMap = new List<MultiCurveUtility.ArcTimeLength>();
arcTimeLengthMap.Add(new MultiCurveUtility.ArcTimeLength(0.0f, 0.0f));
for (int i = 1; i <= resolution; i++)
{
float t = ((float)i) * ratio;
Vector3 p1 = SelectedSpline.Evaluate(t);
arcLength += Vector3.Distance(p0, p1);
arcTimeLengthMap.Add(new MultiCurveUtility.ArcTimeLength(t, arcLength));
p0 = p1;
}
float target = u * arcLength;
int low = 0;
int high = 1;
float min = 0.0f;
float max = 0.0f;
for (int i = 1; i < arcTimeLengthMap.Count; i++)
{
max = arcTimeLengthMap[i].ArcLength;
if (target > min && target < max)
{
high = i;
low = i - 1;
break;
}
min = max;
}
float p = (target - min) / (max - min);
float lowTime = arcTimeLengthMap[low].ArcTime;
float highTime = arcTimeLengthMap[high].ArcTime;
float lowHighDelta = highTime - lowTime;
return arcTimeLengthMap[low].ArcTime + (lowHighDelta * p);
}
上記のコードでは、x 軸の一定速度での移動を表す 3 次ベジエ曲線上のポイントを評価するために使用できる時間を返すために、0 と 1 の間の time(u) を渡しています。
結果は次のとおりです 。Cubic Bezier Image
赤い点は、ベジェ式で元の時間を評価するだけで返される通常のポイントを表します。黄色の点は、近似された時間が経過した後の「一定の」速度位置を表します。接線をかなり誇張するように変更し始めるまでは、かなり正確に見えます。間隔を広げてみましたが、何の役にも立ちません。
とにかく、どんな助けも素晴らしいでしょう。私はまだ数式を読むのが得意ではありません (問題の原因は確かです)。そのため、コード例を使用してヘルプを得ることができれば幸いです。:>
ありがとう!