C#中Random快速调用返回重复值,无需Thread.Sleep如何解决?
问题原因
该现象本质就是代码运行速度过快导致的,核心和Random类的种子生成机制有关:
- 无参构造的
Random实例默认使用系统时钟的当前滴答数作为随机种子,而系统时钟的更新精度通常只有10~15ms,短时间内连续实例化多个Random时,系统时钟还未完成更新,所有实例会拿到完全相同的种子,最终生成的随机序列完全一致。 - 加
Thread.Sleep()的作用是等待系统时钟更新到下一个滴答,让每个新Random实例拿到不同种子,所以随机结果恢复正常。 - 调试时能看到不同值是因为断点停留会产生时间间隔,相当于手动引入了延迟,和加Sleep的效果一致,全速运行时没有延迟就会出现输出全相同的问题。
替代解决方案
通用C#场景方案
全局复用同一个Random实例,避免每次调用都重新实例化即可,修改后代码如下:
class Program { // 全局仅实例化一次Random private static readonly Random _random = new Random(); static void Main(string[] args) { var mytest = new Program(); Console.WriteLine(mytest.test()); Console.WriteLine(mytest.test()); Console.WriteLine(mytest.test()); } public int test() { int testrandom = _random.Next(5, 100); return testrandom; } }
如果是多线程场景使用,需要给Random的调用逻辑加锁,避免线程安全问题。
Unity场景专属方案
Unity引擎自带了更适配游戏开发的随机数工具UnityEngine.Random,不需要手动维护实例,直接调用对应API即可:
- 生成随机数直接用
Random.Range(min, max),底层由引擎统一维护随机种子,不会出现短时间调用结果重复的问题。 - 生成随机位置的示例代码:
// 示例:生成范围自定义的三维随机坐标 Vector3 randomPos = new Vector3( Random.Range(0f, 10f), Random.Range(0f, 5f), Random.Range(0f, 20f) ); // 在随机位置生成目标预制体 Instantiate(targetPrefab, randomPos, Quaternion.identity);
如果需要固定随机序列方便问题复现,只需要在游戏初始化时设置一次Random.InitState(自定义种子数值)即可,不需要每次生成随机数都重复设置。
内容的提问来源于stack exchange,提问作者ezgameworkplace
相关产品推荐
相关产品推荐

