rand_from_seed
最后同步日期:2026-04-15 | Godot 官方原文 — rand_from_seed
rand_from_seed
定义
rand_from_seed() 是带种子的随机数生成函数。与普通的随机数不同,只要你提供相同的"种子"(seed),它就会生成完全相同的一串数字。
打个比方:
- 普通随机数(
randi()、randf())像掷骰子——每次结果都不一样,不可预测 - 种子随机数(
rand_from_seed())像用密码本查数字——只要你翻到同一页(同一个种子),查到的数字就完全相同
这有什么用?想象你在做一个地图生成游戏(类似 Minecraft)。你希望玩家分享一串数字(种子),其他玩家输入同样的数字就能得到完全一样的地图。rand_from_seed() 就是实现这种"确定性随机"的工具。
函数签名
// Godot C# 没有直接等价的内置函数
// 替代方案一:使用 .NET 的 System.Random(推荐)
var rng = new System.Random(seed);
int value = rng.Next(); // 随机整数
int nextSeed = rng.Next(); // 可以作为下一个种子
// 替代方案二:使用 Godot 的 RandomNumberGenerator
var rng = new Godot.RandomNumberGenerator();
rng.Seed = (ulong)seed;
ulong godotSeed = rng.Seed;
int value = rng.Randi();func rand_from_seed(seed: int) -> Dictionary
# 返回 { "value": int, "seed": int }参数说明
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
| seed | int | 是 | 随机种子。相同的种子永远产生相同的随机数序列 |
返回值
类型: Dictionary
返回一个字典,包含两个键:
| 键 | 类型 | 说明 |
|---|---|---|
| value | int | 本次生成的随机整数,范围 0 到 2^32 - 1(约 42 亿) |
| seed | int | 下一次调用时使用的种子值。用这个值再次调用 rand_from_seed(),就能得到序列中的下一个随机数 |
代码示例
下面演示如何用 rand_from_seed() 生成一个可重现的随机地图——同样的种子永远生成同样的地形:
using Godot;
using System;
public partial class MapGenerator : Node2D
{
// 导出属性:地图种子(相同种子 = 相同地图)
[Export] public int ExMapSeed = 12345;
// 导出属性:地图宽度(格子数)
[Export] public int ExMapWidth = 10;
// 导出属性:地图高度(格子数)
[Export] public int ExMapHeight = 10;
// 内部变量:地形数据(0=草地, 1=水, 2=山)
private int[,] _terrainMap;
public override void _Ready()
{
GenerateMap();
}
private void GenerateMap()
{
_terrainMap = new int[ExMapWidth, ExMapHeight];
// 用种子初始化随机数生成器
// 相同的 ExMapSeed 永远生成相同的地形
var rng = new Random(ExMapSeed);
for (int x = 0; x < ExMapWidth; x++)
{
for (int y = 0; y < ExMapHeight; y++)
{
// 生成 0-2 之间的随机地形类型
_terrainMap[x, y] = rng.Next(0, 3);
GD.Print($"({x},{y}): 地形类型 {_terrainMap[x, y]}");
}
}
GD.Print($"地图生成完毕,种子: {ExMapSeed}");
}
}extends Node2D
## 导出属性:地图种子(相同种子 = 相同地图)
@export var ex_map_seed: int = 12345
## 导出属性:地图宽度(格子数)
@export var ex_map_width: int = 10
## 导出属性:地图高度(格子数)
@export var ex_map_height: int = 10
## 内部变量:地形数据(0=草地, 1=水, 2=山)
var _terrain_map: Array = []
func _ready() -> void:
generate_map()
func generate_map() -> void:
_terrain_map.clear()
# 用种子初始化随机数生成
var current_seed := ex_map_seed
for x in range(ex_map_width):
var row := []
for y in range(ex_map_height):
# 调用 rand_from_seed,获取随机数和下一个种子
var result := rand_from_seed(current_seed)
var random_value: int = result["value"]
current_seed = result["seed"]
# 把随机数映射到 0-2 的地形类型
var terrain_type := random_value % 3
row.append(terrain_type)
print("(%d,%d): 地形类型 %d" % [x, y, terrain_type])
_terrain_map.append(row)
print("地图生成完毕,种子: %d" % ex_map_seed)注意事项
确定性是核心价值:
rand_from_seed()最大的用途就是"可重现"。只要种子相同,无论在什么设备上、什么时候运行,生成的数字序列都完全一样。这对以下场景至关重要:- 地图生成:玩家可以分享种子来分享地图
- 重播系统:录制游戏时只记录种子和操作,不需要录制每一帧
- 测试调试:用固定种子复现某个 bug
C# 中没有直接等价函数:Godot C# 没有提供和 GDScript
rand_from_seed()一模一样的函数。推荐使用System.Random(seed)来实现类似功能。注意两者的随机算法不同,所以同样的种子在 C# 和 GDScript 中会产生不同的随机序列。如果需要跨语言一致,需要自己实现随机算法或使用 Godot 的RandomNumberGenerator。种子链式调用:
rand_from_seed()返回的新种子是为了让你连续生成随机数。每次调用后,用返回的seed作为下次调用的输入,就能得到一长串不重复的"伪随机"序列。与
seed()的区别:seed()设置全局随机种子,影响后续所有的randi()、randf()调用rand_from_seed()是独立的一次性调用,不影响全局随机状态- 如果你不想干扰其他代码的随机行为,用
rand_from_seed()更安全
不是"真随机":
rand_from_seed()生成的是"伪随机数"——看起来随机,但其实是用数学公式算出来的。对于游戏开发完全够用,但不适合用于密码学或安全相关的场景。
