Procedural Content Generation – Random Number Generation
Random Number Generation in Procedural Content Generation (PCG)
- Purpose
- Acts as the primary “information source” used to define parameters for models/algorithms that create game content (terrain, texture, quests, path networks, etc.).
- In classic computer‐science contexts, the goal is to approximate true randomness (values that cannot be reproduced).
- In PCG, the goal is controlled, repeatable randomness: we want the same input seed to yield the exact same output sequence so that generated content can be recreated any time (e.g., re-loading a save file, sharing a level code).
- True vs. Pseudo
- True random sources: hardware noise, atmospheric static, radioactive decay, camera Brownian motion, etc., usually post-processed through a whitening/randomization algorithm.
- Pseudorandom sources: algorithmic functions that appear random but are 100 % deterministic from the same seed.
Desired Statistical Distribution
- Uniform Distribution
- Every value in the range has equal probability.
- Works for both discrete (integer) and continuous (floating-point) domains.
- Common default because it gives maximal entropy per bit and predictable statistics.
- Other Distributions
- Gaussian/Normal, Poisson, Exponential, etc., can be built on top of the uniform generator.
- Computational cost varies (Box-Muller for Gaussian, alias tables for discrete custom distributions, rejection sampling, Ziggurat, etc.).
- Choice depends on artistic need: e.g., Gaussian for clustered placement, Poisson for natural spacing.
Numeric Mixing & Seeds
- A pseudorandom number generator (PRNG) is fundamentally a mixing function.
- The seed’s bits are iteratively permuted and combined so that each output bit is influenced by many (ideally all) seed bits.
- Determinism property
- Same Seed⇒Same Full Sequence
- Enables reproducible PCG; different seeds produce wholly different worlds.
- Update formulation
- Let S0 be the initial state (equal to or derived from the seed).
- A step of the PRNG can be written S<em>0→S</em>1,r where S1 is the new internal state and r the output random value.
- Repeated calls chain the state: S<em>n→S</em>n+1,rn+1.
Challenges for Perfect Repeatability
- Call Count Consistency
- Even when the same seed is used, the sequence index must match. Any extra or missing call shifts the remainder of the sequence.
- Multiple Subsystems
- Physics, AI, animation, loot rolls, VFX, networking, analytics—all might tap the same RNG.
- An innocent change (new particle spawn) can break level generation determinism.
- Nondeterministic Triggers
- Frame-rate dependent loops (variable update counts).
- External events: human input, network packets, sensor data.
- Guideline: keep strict accounting of every RNG request or use separate generators for isolated systems (see “Isolate RNG”).
Unity Engine Facilities (Example)
Random.InitState(int initialSeed)- Sets the global Unity PRNG state from an integer seed.
Random.Range(int/float a, int/float b)- Discrete or continuous uniform range sampling.
Random.state (get & set)- Struct holding the full internal state; serializable for save games.
- Limitation: you cannot derive the original seed from an arbitrary state snapshot.
- Best practice in Unity: save/restore
Random.state when you enter/exit PCG functions to avoid global contamination.
Isolating RNG per Subsystem
- Provide a root/master seed via a game manager.
- Each subsystem constructs its own local PRNG instance (or keeps its own copy of Unity’s
Random.State). - Benefits
- Changes in one subsystem do not affect the sequence consumed by another.
- Easier debugging—log or serialize each subsystem’s seed/state.
- Facilitates deterministic re-runs of only a subset (e.g., regenerate terrain without re-simulating AI).
- Different operating systems, compilers, CPU architectures, or library versions may embed distinct PRNG algorithms (e.g., Microsoft
rand() vs. glibc rand()). - Small, seemingly harmless updates (SDK, driver, console firmware) can silently change RNG results.
- Mitigation: ship your own PRNG implementation inside the codebase.
- Guarantees bit-identical output across Windows, macOS, Linux, PS5, Xbox, Switch, mobile, etc.
- Allows forward compatibility; if you upgrade the algorithm you can still keep legacy generators around for old saves.
- Popular Choice: Mersenne Twister (MT19937)
- Period of 219937−1, excellent statistical quality, fast.
- But not cryptographically secure (fine for games/fairness, unsafe for security tokens).
Quality of RNG & Post-Processing
- Raw RNG output is high-frequency noise—usually unsuitable as‐is for content.
- Example: If you directly map height values to a terrain mesh, you get unplayable spiky landscapes.
- Typical pipeline
- RNG ➔ Noise function (Perlin, Simplex) ➔ Filtering/Smoothing ➔ Domain-specific model.
- Visual Example (Millington Fig 8.7)
- Pure elevation noise displayed as a gray-scale height map: looks like TV static; needs filtering to become rolling hills.
Practical / Ethical / Philosophical Implications
- Fairness & Transparency
- Deterministic seeds allow players to share world codes—bolstering community and e-sports fairness.
- Conversely, hidden seed usage can hide drop-rate manipulation; transparency matters.
- Creative Control vs. Surprise
- Designers oscillate between wanting handcrafted predictability and emergent unpredictability. Seeded PRNG offers a middle ground: controlled chaos.
- Preservation & Archiving
- Repeatable RNG lets future researchers, speed-runners, or historians regenerate worlds and study them long after original servers shut down.