tanh
2026/4/15大约 3 分钟
最后同步日期:2026-04-15 | Godot 官方原文 — tanh
tanh
定义
tanh() 是双曲正切函数(hyperbolic tangent)。你也许已经用过普通的 tan()(正切函数),它的输出可以无限大。而 tanh() 的特殊之处在于:不管你输入多大的数,输出永远被"压缩"在 -1 到 1 之间。
打个比方:就像音量旋钮——你可以拼命往右拧,但扬声器有最大音量限制,声音不会无限大。tanh() 就是数学世界里的"音量限制器"。
这个函数在机器学习(神经网络的激活函数)和游戏中的数值平滑处理非常常见。
函数签名
C#
// 方式一:使用 Godot 的 Mathf(推荐,返回 float)
public static float Tanh(float x)
// 方式二:使用 .NET 标准库(返回 double)
public static double Tanh(double x)GDScript
func tanh(x: float) -> float参数说明
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
| x | float | 是 | 输入值,可以是任意实数(正数、负数、零都可以) |
返回值
类型: float
返回 x 的双曲正切值,范围固定在 -1.0 到 1.0 之间。
| 输入 | 输出 | 说明 |
|---|---|---|
| 很大的正数(如 100.0) | 接近 1.0 | 正方向"饱和" |
| 0.0 | 0.0 | 原点处输出恰好为零 |
| 很大的负数(如 -100.0) | 接近 -1.0 | 负方向"饱和" |
代码示例
下面是一个角色移动速度平滑衰减的例子——速度越快,加速效果越小,自然形成"速度上限":
C#
using Godot;
public partial class Player : CharacterBody2D
{
// 导出属性:编辑器中可配置的最大速度
[Export] public float ExMaxSpeed = 300f;
// 内部变量:当前加速度输入
private float _accelInput = 5f;
public override void _PhysicsProcess(double delta)
{
// tanh 把加速度"压缩"到 -1 ~ 1 之间
// 乘以 ExMaxSpeed 后,速度永远不会超过 ExMaxSpeed
float speedFactor = Mathf.Tanh(_accelInput);
float currentSpeed = speedFactor * ExMaxSpeed;
// 模拟持续加速(每帧增加一点输入值)
_accelInput += 0.02f;
GD.Print($"速度因子: {speedFactor:F2}, 当前速度: {currentSpeed:F1}");
}
}GDScript
extends CharacterBody2D
## 导出属性:编辑器中可配置的最大速度
@export var ex_max_speed: float = 300.0
## 内部变量:当前加速度输入
var _accel_input: float = 5.0
func _physics_process(delta: float) -> void
# tanh 把加速度"压缩"到 -1 ~ 1 之间
# 乘以 ex_max_speed 后,速度永远不会超过 ex_max_speed
var speed_factor := tanh(_accel_input)
var current_speed := speed_factor * ex_max_speed
# 模拟持续加速(每帧增加一点输入值)
_accel_input += 0.02
print("速度因子: %.2f, 当前速度: %.1f" % [speed_factor, current_speed])注意事项
- 输出范围固定:
tanh()的输出严格在 -1 到 1 之间(开区间),永远不会等于或超出这个范围。这使得它非常适合做"软限制"(soft clamp),比clamp()更平滑。 - 与
tan()的区别:tan()是三角函数,输入是角度(弧度),输出可以无限大;tanh()是双曲函数,输入是实数,输出被限制在 -1 到 1 之间。两者虽然名字相似,但数学含义完全不同。 - 与
sign()的对比:sign()是生硬的跳变(-1、0、1),而tanh()在正负之间平滑过渡。如果你需要一个"平滑版的方向判断",tanh()是好选择。 - C# 中的选择:在 Godot C# 中推荐使用
Mathf.Tanh()(返回float),而不是Math.Tanh()(返回double),这样可以避免不必要的类型转换。
