inverse_lerp
最后同步日期:2026-04-15 | Godot 官方原文 — inverse_lerp
inverse_lerp
定义
inverse_lerp() 是 lerp() 的"反向操作"。lerp() 是"给我起点、终点和一个百分比,我算出中间值";而 inverse_lerp() 是"给我起点、终点和一个中间值,我告诉你这个值在起点和终点之间的百分比位置"。
打个比方:考试满分 100 分,及格线 60 分。如果你考了 80 分,inverse_lerp(60, 100, 80) 就告诉你:80 分在 60 到 100 之间的位置是 50%——也就是你刚好在及格线和满分正中间。
再比如:温度计显示 25 度,你知道今天的最低温是 10 度、最高温是 40 度。inverse_lerp(10, 40, 25) 返回 0.5,意思是 25 度正好在今天的温度范围正中间。
什么时候需要用到它?
- 把一个值转换成 0~1 的百分比(用于 UI 进度条、滑动条等)
- 判断某个值在一个范围内处于什么位置
- 配合
lerp()或remap()实现范围转换
函数签名
public static float InverseLerp(float from, float to, float value)func inverse_lerp(from: float, to: float, value: float) -> float参数说明
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
from | float | 是 | 范围的起始值。对应百分比 0% |
to | float | 是 | 范围的结束值。对应百分比 100% |
value | float | 是 | 你想知道位置的那个值 |
返回值
float -- 返回 value 在 from 和 to 之间的位置比例。计算公式为 (value - from) / (to - from)。
- 当
value == from时返回 0.0 - 当
value == to时返回 1.0 - 当
value在中间时返回 0~1 之间的值 - 当
value超出范围时,返回值可能小于 0 或大于 1
代码示例
基础用法:计算百分比位置
using Godot;
public partial class InverseLerpExample : Node
{
public override void _Ready()
{
// 80 在 60 到 100 之间的什么位置?
float result1 = Mathf.InverseLerp(60f, 100f, 80f);
GD.Print(result1); // 运行结果: 0.5(正中间)
// 25 在 10 到 40 之间的什么位置?
float result2 = Mathf.InverseLerp(10f, 40f, 25f);
GD.Print(result2); // 运行结果: 0.5(正中间)
// 30 在 0 到 100 之间的什么位置?
float result3 = Mathf.InverseLerp(0f, 100f, 30f);
GD.Print(result3); // 运行结果: 0.3(30% 位置)
// 超出范围:150 在 0 到 100 之间?
float result4 = Mathf.InverseLerp(0f, 100f, 150f);
GD.Print(result4); // 运行结果: 1.5(超出范围了)
}
}func _ready():
# 80 在 60 到 100 之间的什么位置?
var result1 = inverse_lerp(60.0, 100.0, 80.0)
print(result1) # 运行结果: 0.5(正中间)
# 25 在 10 到 40 之间的什么位置?
var result2 = inverse_lerp(10.0, 40.0, 25.0)
print(result2) # 运行结果: 0.5(正中间)
# 30 在 0 到 100 之间的什么位置?
var result3 = inverse_lerp(0.0, 100.0, 30.0)
print(result3) # 运行结果: 0.3(30% 位置)
# 超出范围:150 在 0 到 100 之间?
var result4 = inverse_lerp(0.0, 100.0, 150.0)
print(result4) # 运行结果: 1.5(超出范围了)实际场景:血条 UI 显示
using Godot;
public partial class HealthBar : Control
{
// 导出属性:血量条节点
[Export] public ColorRect ExBarFill = null;
// 导出属性:最大血量
[Export] public float ExMaxHealth = 100.0f;
// 内部变量:当前血量
private float _currentHealth = 75.0f;
public void UpdateHealthBar()
{
// 把当前血量转换为 0~1 的百分比
float healthPercent = Mathf.InverseLerp(0f, ExMaxHealth, _currentHealth);
// 限制在 0~1 之间
healthPercent = Mathf.Clamp(healthPercent, 0f, 1f);
// 设置血条宽度(假设血条宽度 = 200 像素)
ExBarFill.Size = new Vector2(200f * healthPercent, ExBarFill.Size.Y);
GD.Print($"血量: {_currentHealth}/{ExMaxHealth} = {healthPercent * 100}%");
// 运行结果: 血量: 75/100 = 75%
}
}extends Control
# 导出属性:血量条节点
@export var bar_fill: ColorRect
# 导出属性:最大血量
@export var max_health: float = 100.0
# 内部变量:当前血量
var _current_health: float = 75.0
func update_health_bar():
# 把当前血量转换为 0~1 的百分比
var health_percent = inverse_lerp(0.0, max_health, _current_health)
# 限制在 0~1 之间
health_percent = clampf(health_percent, 0.0, 1.0)
# 设置血条宽度(假设血条宽度 = 200 像素)
bar_fill.size = Vector2(200.0 * health_percent, bar_fill.size.y)
print("血量: %d/%d = %d%%" % [_current_health, max_health, health_percent * 100])
# 运行结果: 血量: 75/100 = 75%进阶用法:配合 lerp 实现范围转换
using Godot;
public partial class RangeConverter : Node
{
public override void _Ready()
{
// 场景:把经验值(0~1000)映射到等级(1~10)
float exp = 350.0f;
float maxExp = 1000.0f;
// 第一步:用 inverse_lerp 把经验值变成百分比
float progress = Mathf.InverseLerp(0f, maxExp, exp);
GD.Print($"进度: {progress * 100}%"); // 运行结果: 进度: 35%
// 第二步:用 lerp 把百分比映射到等级范围
float level = Mathf.Lerp(1f, 10f, progress);
GD.Print($"对应等级: {level}"); // 运行结果: 对应等级: 4.15
// 以上两步等价于使用 remap
float levelViaRemap = Mathf.Remap(exp, 0f, maxExp, 1f, 10f);
GD.Print($"remap 结果: {levelViaRemap}"); // 运行结果: remap 结果: 4.15
}
}func _ready():
# 场景:把经验值(0~1000)映射到等级(1~10)
var exp = 350.0
var max_exp = 1000.0
# 第一步:用 inverse_lerp 把经验值变成百分比
var progress = inverse_lerp(0.0, max_exp, exp)
print("进度: %d%%" % (progress * 100)) # 运行结果: 进度: 35%
# 第二步:用 lerp 把百分比映射到等级范围
var level = lerp(1.0, 10.0, progress)
print("对应等级: ", level) # 运行结果: 对应等级: 4.15
# 以上两步等价于使用 remap
var level_via_remap = remap(exp, 0.0, max_exp, 1.0, 10.0)
print("remap 结果: ", level_via_remap) # 运行结果: remap 结果: 4.15注意事项
当
from等于to时会除零:如果from和to相同,函数会因为分母为零而返回不可预期的结果(通常是 NaN 或无穷大)。使用前请确保from和to不同。返回值可以超出 0~1:如果
value比from小或比to大,返回值会小于 0 或大于 1。如果你需要结果严格在 0~1 之间,请在外层套用Mathf.Clamp()/clampf()。from可以大于to:反向范围也是合法的。例如inverse_lerp(100, 0, 75)返回 0.25,意思是 75 在从 100 降到 0 的路上走了 25%。与
lerp()的关系:inverse_lerp(from, to, value)是lerp(from, to, weight)的逆运算。也就是说,lerp(from, to, inverse_lerp(from, to, value))应该返回value本身(在不超出范围的情况下)。等价于
remap的前半部分:inverse_lerp(a, b, x)的效果等同于remap(x, a, b, 0, 1)。
