讓隨機錯誤可以重現:以種子重現遊戲中的隨機結果
Seed the Chaos: Making Random Bugs Reproducible
遊戲開發者可記錄每次遊戲執行的初始隨機種子和 build,讓隨機錯誤能按相同種子、build 和輸入順序重現。自動化測試可執行使用種子的遊戲,記下失敗種子、build 和失敗的 assertion,方便核查缺陷。種子無法解決競態條件、記憶體壓力、硬件差異或時間問題,但可為排查提供具體起點。
Every game that shuffles, spawns or rolls dice has a quiet problem: the bug that happened once and never again.
A tester sees the shop hand out the wrong reward. Nobody can make it happen twice. Without a way back to that exact run, the report is stuck: someone saw something, and nobody can prove what.
Randomness feels like the enemy of testing. It does not have to be. The same generator that makes a run unpredictable can make it exactly repeatable, if you keep one small piece of information: the seed.
A seed is a recipe, not a recording
Most engines let you set the starting seed of their random number generator. Godot's RandomNumberGenerator does. Give two runs the same seed and the generator produces the same sequence of numbers in both.
That gets you most of a replay, not all of it. An exact replay needs the same seed, the same code, the same engine version and the same inputs in the same order. Change any of them and the same seed tells a different story. A seed is the recipe for the randomness, not a recording of the run.
Two habits make seeds useful. Log the initial seed at the start of every run, meaning the seed the run began with, not the generator's later state. And log the build with it, so "cannot reproduce" at least means "cannot reproduce on this version".
Chaos, but on a schedule
Once every run has a seed, testing stops needing luck.
The practical setup is simple: an automated job plays seeded games and writes one line per failure - the seed it started from, the build, and the assertion that broke. The review comes down to three questions. Did anything fail? Does it fail again on the same seed and the same build? Is the failing state a real defect, or an expectation that aged?
On a quiet day the answers take minutes. On the day that matters, there is a reproduction already in hand instead of a theory.
The honest limits
Determinism covers logic. It does not cover timing, floating-point differences across devices, or the physics of a real thumb. A seeded replay can prove the shuffle behaved for that seed on that build. It cannot prove the game felt fair, any more than a passing screenshot proves a player understood the screen. I wrote about that boundary in an earlier piece (https://dev.to/kfiradut/a-test-report-should-say-what-it-cannot-prove-3i0i); it applies here with full force.
And some real defects stay intermittent even with seeds: race conditions, memory pressure, hardware quirks. A seed does not solve those. It gives every report somewhere concrete to start, instead of a shrug.
Why it is worth it
Reproducible randomness is not only for debugging. It is a design tool.
Balance questions stop being arguments from one lucky session. You can run a difficulty change across the same thousand seeds as the old one and compare what actually moved. The randomness becomes a fixed laboratory instead of weather.
Chaos is fine. Seed it first.
In my game projects, Instinct does much of the implementation and testing. I stay responsible for direction and for the decision to ship.
References:
- RandomNumberGenerator - Godot Engine documentation: https://docs.godotengine.org/en/stable/classes/class_randomnumbergenerator.html
- Random number generation - Godot Engine documentation: https://docs.godotengine.org/en/stable/tutorials/math/random_number_generation.html
來源:DEV Community · dev.to