Search Unity

Question how to make sure that everything involving randomness will look the same on every play?

Discussion in 'Scripting' started by taowenbo1993, May 28, 2023.

  1. taowenbo1993

    taowenbo1993

    Joined:
    Feb 12, 2022
    Posts:
    12
    For example, I want particle systems and shaders that use randomness to look the same way on each play.

    For one particle, I know that I could use `useAutoRandomSeed=false`. But I have a ton of particles in the project. I don't want to set that for each one, and I don't know how to set that globally. This also doesn't work for shaders.

    Appreciate any pointers, thanks!
     
  2. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,445
    For your own logic, you can get your own PRNG instance and only use that. For Unity's built-in systems like particles, not likely. Any update to the logic between builds of Unity could consume a different number of values from their PRNG instance, and thus throw off your determinism.

    Note that if your code does anything with Time.deltaTime instead of an integer frame index (by far the most recommended path), you're probably also going to get out of sync with any pre-recorded frame sequence. Almost no game platform target is 100% guaranteed to lock the frame rate to exactly your target rate anymore... you need a realtime OS and a significant timesafe margin to avoid accidental time overruns. Once you skip a frame or get an extra frame, your own chances of accidentally consuming a different number of values from your PRNG instance goes way up.

    Not even Nintendo, who is famously allergic to random numbers, goes as far as locking down the shaders.
     
  3. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    I cant comment on the particle system specifically, but generally speaking everything pseudo-random a computer does relies on a seed. There is no true randomnes possible in a computer. Using the same seed will thus produce the same sequences of "random" numbers, and thus produces the same behavior.

    So for any given feature where randomnes is involved and for which you want to make sure it is reproducible you need to make sure the same seed is used. While there may be helpful features, like the mentioned useAutoRandomSeed setting, for things like the particle system, i would usually make sure the same seed is used programmatically. Again, i cant really comment on the particle system specifically as i dont have any experience there.

    Shader languages, unlike for example C#, dont even have a function to generate a random number. So whoever introduced randomnes into a shader wrote their own pseudo-random number generator function and would have to make sure it also allows to produce reproducible results.
     
  4. AngryProgrammer

    AngryProgrammer

    Joined:
    Jun 4, 2019
    Posts:
    490
    In Unity, you can always write a custom shader (in Shader Graph) in which you can use your parameters (like a seed). I don't help here much more, but maybe this will add some help in future searches.
     
  5. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,114
    Random values in shaders are typically there only for cosmetic purposes, they just have to look good or satisfy some property, i.e. apparent-aperiodicity or seed-based repetition or gradient blending (as with simplex noises).

    Here's a couple of ways to produce a white-noise-like hash in shader code [link1] [link2] [link3].
    Here's how to implement a fully fledged PCG [link].

    I'm not sure what to do with the particle systems, though. Probably there is a way to customize the motion and then introduce a custom randomization, I don't know really.
     
  6. Adrian

    Adrian

    Joined:
    Apr 5, 2008
    Posts:
    1,066
    You cannot set it globally, you have to set it on every particle system. The best would be to put a script on every particle system. You could try to do this automatically but handling prefabs will be tricky and you'll have to make sure you disable
    useAutoRandomSeed
    before it starts spawning.

    Also, fixing the random seed is only part of what's required to make things always the same. You also need to make sure the random numbers are used in the same order, I'm not actually sure to what extent a fixed random seed on a particle system will guarantee this. If you e.g. dynamically modify a particle system, it might be difficult to make this with accurate enough timing for the simulation to stay deterministic.
     
  7. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,114
    That's a good point. Random number generators are only really stateless hash functions, so all they do is to produce a sequence of quasi-independent values, so that the same sequence will always follow the same seed value (making it appear as if a seed is 'producing' that sequence). So changing the way or order the values are consumed will drastically change the apparent outcome.