3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

可変FPSなUnityで指数関数による速度変化

Last updated at Posted at 2024-03-13

例えばあるキャラクターが速度speed、
位置posという値を持っているとします。

で「ググーッと急ブレーキで止まる」みたいなことやらせたいからと、
毎フレームの位置と速度の更新を
下記のようにやってしまうとFPSが変化した時に挙動が変わってしまう。

float speed = 1; // 初速
Vector3 pos; // 現在位置
const float breakPow = 0.05f; // ブレーキ力。1未満。大体0.001から0.05ぐらいが実用的

// 毎フレーム呼び出し
void Update()
{
    // 速度更新
    speed *= (1 - breakPow); // 掛け算でブレーキ。ググーッと止まる

    // 位置更新
    pos.x += speed * Time.deltaTime;
}

FixedUpdateを使う、速度ではなく位置をイージングするなど対処方法はあるのですが、今回は数学で。

ということで、まず速度の変更はこうします。

// 指数関数で補間
float Interpolate(float from, float to, float pow, int fps, float t)
{
    float rate = 1 - Mathf.Pow(1 - pow, fps * t);
    return Mathf.Lerp(from, to, rate);
}

// 毎フレーム呼び出し
void Update()
{
    const int FPS = 120; // 基準となるFPS

    // FPSが変わっても大丈夫なように速度更新
    speed = Interpolate(speed, 0, breakPow, FPS, Time.deltaTime);

    // さて、移動量は・・・積分が必要!
    //pos.x += speed * Time.deltaTime;
}

あとは位置の更新ですが、こちらは定積分が必要。
もはや積分のことなんてとっくに忘れてしまったので、
ChatGPTさんにやってもらいました。

これが結果。

// fromからtoに向かって変化する場合の[0からt]までの定積分
float CalcDefiniteIntegral(float from, float to, float pow, int fps, float t)
{
    var a = to;
    var b = from - to;
    var p = 1 - pow;
    var q = fps;
    return a * t + b / (q * Mathf.Log(p)) * (Mathf.Pow(p, q * t) - 1);
}

ということでまとめるとこんな感じ。

// 毎フレーム呼び出し
void Update()
{
    const int FPS = 120; // 基準となるFPS

    // FPSが変わっても大丈夫なように位置更新
    pos.x += CalcDefiniteIntegral(speed, 0, breakPow, FPS, Time.deltaTime);

    // FPSが変わっても大丈夫なように速度計算
    speed = Interpolate(speed, 0, breakPow, FPS, Time.deltaTime);
}
3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?