randfn
2026/4/14大约 5 分钟
最后同步日期:2026-04-15 | Godot 官方原文 — randfn
randfn
定义
randfn() 用于生成一个正态分布(也叫"高斯分布")的随机浮点数。它和 randf()、randf_range() 的关键区别在于:普通随机数在每个值出现的概率是均等的(均匀分布),而正态分布的随机数越靠近中间值,出现的概率越高。
想象你在投飞镖:普通随机数就像闭着眼睛往靶子上随便扎,扎到哪里概率都差不多。正态分布就像一个高手投飞镖——大部分飞镖都集中在靶心附近(中间值),偶尔有几镖会偏离较远。
正态分布有两个参数:
- 均值(mean):飞镖瞄准的中心点,出现概率最高的值
- 偏差(deviation):飞镖偏离中心的程度,偏差越大,飞镖散得越开
函数签名
C#
// C# 中使用 GD.Randfn
float value = GD.Randfn(float mean, float deviation);GDScript
func randfn(mean: float = 0.0, deviation: float = 1.0) -> float参数说明
| 参数 | 类型 | 必需 | 默认值 | 说明 |
|---|---|---|---|---|
mean | float | 否 | 0.0 | 正态分布的均值(中心值),生成结果最可能出现在这个值附近 |
deviation | float | 否 | 1.0 | 正态分布的标准差(偏差),值越大,结果分散得越远 |
返回值
float —— 一个符合正态分布的随机浮点数。大约 68% 的结果会落在 [mean - deviation, mean + deviation] 范围内,95% 落在 [mean - 2*deviation, mean + 2*deviation] 范围内。
代码示例
基础用法:正态分布随机数
C#
using Godot;
public partial class RandfnExample : Node
{
public override void _Ready()
{
// 默认参数:均值 0,偏差 1
float value1 = GD.Randfn();
GD.Print($"标准正态: {value1:F4}");
// 运行结果: 标准正态: 0.7321
// 自定义均值和偏差:均值 100,偏差 15
float value2 = GD.Randfn(100f, 15f);
GD.Print($"成绩分布: {value2:F1}");
// 运行结果: 成绩分布: 103.5
}
}GDScript
extends Node
func _ready():
# 默认参数:均值 0,偏差 1
var value1 = randfn()
print("标准正态: %.4f" % value1)
# 运行结果: 标准正态: 0.7321
# 自定义均值和偏差:均值 100,偏差 15
var value2 = randfn(100.0, 15.0)
print("成绩分布: %.1f" % value2)
# 运行结果: 成绩分布: 103.5实际场景:角色属性生成
C#
using Godot;
public partial class CharacterGenerator : Node
{
public void GenerateCharacter(string name)
{
// 用正态分布生成属性:大部分角色属性集中在均值附近
int str = (int)GD.Randfn(50f, 10f); // 力量:均值 50,偏差 10
int dex = (int)GD.Randfn(50f, 10f); // 敏捷
int intel = (int)GD.Randfn(50f, 10f); // 智力
// 限制在合理范围内
str = Mathf.Clamp(str, 1, 100);
dex = Mathf.Clamp(dex, 1, 100);
intel = Mathf.Clamp(intel, 1, 100);
GD.Print($"{name}: 力量={str} 敏捷={dex} 智力={intel}");
}
public override void _Ready()
{
GenerateCharacter("战士");
GenerateCharacter("法师");
GenerateCharacter("盗贼");
// 运行结果(每次不同,但大部分值在 40~60 之间):
// 战士: 力量=55 敏捷=42 智力=38
// 法师: 力量=31 敏捷=48 智力=62
// 盗贼: 力量=44 敏捷=58 智力=47
}
}GDScript
extends Node
func generate_character(name: String) -> void:
# 用正态分布生成属性:大部分角色属性集中在均值附近
var str = int(randfn(50.0, 10.0)) # 力量:均值 50,偏差 10
var dex = int(randfn(50.0, 10.0)) # 敏捷
var intel = int(randfn(50.0, 10.0)) # 智力
# 限制在合理范围内
str = clampi(str, 1, 100)
dex = clampi(dex, 1, 100)
intel = clampi(intel, 1, 100)
print("%s: 力量=%d 敏捷=%d 智力=%d" % [name, str, dex, intel])
func _ready():
generate_character("战士")
generate_character("法师")
generate_character("盗贼")
# 运行结果(每次不同,但大部分值在 40~60 之间):
# 战士: 力量=55 敏捷=42 智力=38
# 法师: 力量=31 敏捷=48 智力=62
# 盗贼: 力量=44 敏捷=58 智力=47进阶用法:子弹散射效果
C#
using Godot;
public partial class Weapon : Node2D
{
[Export] public float ExBaseDamage = 50f;
[Export] public float ExDamageVariation = 10f;
[Export] public float ExSpreadAngle = 5f;
public void Fire()
{
// 用正态分布生成散射角度:大部分子弹接近瞄准方向
float spread = GD.Randfn(0f, ExSpreadAngle);
float rad = Mathf.DegToRad(spread);
// 用正态分布生成伤害波动:大部分伤害接近基础值
float damage = GD.Randfn(ExBaseDamage, ExDamageVariation);
damage = Mathf.Max(damage, 1f);
GD.Print($"发射!散射角度: {spread:F1}度, 伤害: {damage:F1}");
}
public override void _Ready()
{
// 模拟连续射击 5 发
for (int i = 0; i < 5; i++)
{
Fire();
}
}
}GDScript
extends Node2D
@export var ex_base_damage: float = 50.0
@export var ex_damage_variation: float = 10.0
@export var ex_spread_angle: float = 5.0
func fire() -> void:
# 用正态分布生成散射角度:大部分子弹接近瞄准方向
var spread = randfn(0.0, ex_spread_angle)
var rad = deg_to_rad(spread)
# 用正态分布生成伤害波动:大部分伤害接近基础值
var damage = randfn(ex_base_damage, ex_damage_variation)
damage = maxf(damage, 1.0)
print("发射!散射角度: %.1f度, 伤害: %.1f" % [spread, damage])
func _ready():
# 模拟连续射击 5 发
for i in range(5):
fire()注意事项
与均匀分布的区别:
randf_range(0, 10)每个值出现的概率相等(均匀分布)。randfn(5, 2)大部分结果在 3~7 之间,偶尔出现 0 或 10(正态分布)。根据你的需求选择合适的函数。结果不限于
[mean - deviation, mean + deviation]:正态分布理论上没有上下限。虽然大部分结果(约 68%)在这个范围内,但偶尔会产生远超此范围的极端值。如果需要限制范围,请配合Mathf.Clamp()使用。典型应用场景:角色属性生成、伤害波动、子弹散射角度、身高体重模拟、自然界数据模拟等——凡是真实世界中"大多数普通、少数极端"的数据分布,都适合用正态分布。
C# 中使用
GD.Randfn():C# 中对应的函数是GD.Randfn(),行为一致。
