0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Unity C#】値をマッピングする計算

Last updated at Posted at 2025-11-05

ゲームでは数学的な計算をする場面が多いです。
特に、時間の関数となることが多いでしょう。

  • 物体を一定速度で動かす(時間に対して位置が変化)
  • スプライトの透明度を変化させてフェードアウト(時間に対して透明度が変化)

DOTween というライブラリが有名ですが、
ただ純粋な線形変換(直線的な補完)をしたいだけならオーバーキルかもしれません。
ラムダ式で GC.Alloc とか発生しますしね。(関連する話

面倒臭いコード

参考

DOVirtual.Float(
  from     : 1.0f, // Tween開始時の値
  to       : 5.0f, // 終了時の値
  duration : 1.0f, // Tween時間
  // 値が変化するたびに実行される
  onVirtualUpdate: value => {
    // "value" を使った処理
  }
).SetEase(Ease.Linear); // 線形イースにする

線形変換とか言いましたが、やっていることは本質的に直線の方程式です。
意外と簡単な気がしませんか?

f(x) = A(x - B) + C

この直線の方程式を汎用的なメソッドにしてみました。

作成したプログラム
using System.Runtime.CompilerServices;
using UnityEngine;

public static class RemapUtils
{
    /// <summary>
    /// 区間を線形変換します。<br/>
    /// value の定義域は [<see cref="fromMin"/>, <see cref="fromMax"/>] に留まりません。<br/>
    /// ------------------------------<br/>
    /// 言い換えると、直線の方程式です。<br/>
    /// 2点 (<see cref="fromMin"/>, <see cref="toMin"/>), (<see cref="fromMax"/>, <see cref="toMax"/>) を通る直線について、<br/>
    /// x = <see cref="value"/> の時の y の値を返します。<br/>
    /// ------------------------------<br/>
    /// ※ 0除算はチェックしません。<br/>
    /// ※ 本質的に直線の方程式なので、実は引数の値の大小関係は問いません。<br/>
    /// <example>
    /// <code>
    /// 2f.Remap(1f, 3f, 4f, 8f)  // 6f
    /// 2f.Remap(1f, 1f, 4f, 8f)  // 0除算!
    /// 2f.Remap(3f, 1f, 8f, 4f)  // 6f
    /// </code>
    /// </example>
    /// </summary>
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static float Remap(this float value, float fromMin, float fromMax, float toMin, float toMax)
        => (value - fromMin) * (toMax - toMin) / (fromMax - fromMin) + toMin;

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static Vector2 Remap(this float value, float fromMin, float fromMax, Vector2 toMin, Vector2 toMax)
        => (value - fromMin) * (toMax - toMin) / (fromMax - fromMin) + toMin;

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static Vector3 Remap(this float value, float fromMin, float fromMax, Vector3 toMin, Vector3 toMax)
        => (value - fromMin) * (toMax - toMin) / (fromMax - fromMin) + toMin;

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static Color Remap(this float value, float fromMin, float fromMax, Color toMin, Color toMax)
        => (value - fromMin) * (toMax - toMin) / (fromMax - fromMin) + toMin;
}

大事な所を抜き出してみます。

float Remap(float value, float fromMin, float fromMax, float toMin, float toMax)
    => (value - fromMin) * (toMax - toMin) / (fromMax - fromMin) + toMin;

valuefromMin から fromMax まで変化する時、
戻り値は toMin から toMax の範囲に線形変換されます。

以下のように傾きが計算され、上記の式に従って計算を行います。

float A = (toMax - toMin) / (fromMax - fromMin);
return (value - fromMin) * A + toMin;

拡張メソッドにしてあるので、このように使うことができます。ちょっと便利。

_ = 2f.Remap(1f, 3f, 4f, 8f);  // 6f
0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?