17
\$\begingroup\$

Is unity engines random number generator deterministic across platforms given the same initial seed or should I implement my own?

I know there have been some modifications to the random number generator recently.

Answers are appreciated, I don't have the devices on hand to perform any tests and I haven't yet found a direct statement on the matter.

\$\endgroup\$
  • 11
    \$\begingroup\$ Good question. But when your game depends on deterministic procedural generation, you might want to program your own PRNG anyway in case Unity ever decides to change their algorithm. The documentation doesn't document the algorithm, so you should not assume any guarantees. \$\endgroup\$ – Philipp Oct 13 '17 at 13:03
  • 1
    \$\begingroup\$ I understand your point, but there is enough work to be getting on with, I'd rather learn what state unity's PRNG is in right now and provide a future proof version further down the line. Using it without knowing might lead to some really frustrating bugs. Thanks for your advice. \$\endgroup\$ – eternalNoob Oct 13 '17 at 16:02
  • 2
    \$\begingroup\$ I second @Philipp's advice. If you need a deterministic RNG you should invest in writing your own (and testing it). You will be in a world of hurt if you ever need to use a new Unity version and the RNG changed again. It will be near impossible for you to recreate the same RNG if this happens and keep compatibility with previous saves/worlds. \$\endgroup\$ – Stephane Hockenhull Oct 26 '17 at 22:26
  • 5
    \$\begingroup\$ I think that advice would be worth writing up as an answer, "Whether it is or is not deterministic now, don't count on it always being the same" (If either of you would be so inclined — I don't want to steal your thunder). Some ostensibly yes or no questions are better answered with "option C: other" ;) \$\endgroup\$ – DMGregory Oct 26 '17 at 22:38
8
\$\begingroup\$

While I haven't had time to do any extensive testing, initial research suggests that the random number generator used is deterministic across different platforms. The exact implementation used is: Unity PRNG. See also: Unity Random Seed On Different Hardware.
With the Unity Random class, the exact state of the PRNG can be saved, see: Unity Random Sate.

\$\endgroup\$
7
+100
\$\begingroup\$

Thomas answered the question as asked. The more important question is as follows:

Is the Unity 2017 random number generator guaranteed to deliver the same numbers across all current and future platforms given the same seed, and is it also guaranteed to deliver the same numbers as future releases of Unity?

There is a rather high likelihood for this being the case, but that isn't the same as a guarantee. So the answer, unfortunately, is "no, it is not". A guarantee would need to be explicitly stated in the documentation of Random, but currently there is no such thing.

Personally, even if there were such a guarantee, I'd recommend not to trust it - even with a guarantee there's still a chance of the implementation being changed by accident (a bug), or simply being deprecated and later removed. At some point you also might want to reuse the generator outside of the Unity framework. Instead of relying on Unity, just copy a random number generator someone else wrote (make sure you're allowed to use the code), and write a test to verify it satisfies your requirements for randomness.

\$\endgroup\$
4
\$\begingroup\$

Using Unity 2017.2.0f3, UnityEngine.Random appears to give the same results across multiple platforms. Tested on Windows 10, macOS 10.12 Sierra, and Android 7.

To test, I trimmed down a SeedFactory class I've created:

using UnityEngine;

public class SeedFactory {

    private Random.State state;

    public SeedFactory (int seed) {
        Random.InitState(seed);
        state = Random.state;
    }

    // Set Unity's global Random state with this SeedFactory's state, get a random int,
    // then set our SeedFactory's state with the new state.
    // (this allows us to use multiple SeedFactories for multiple paths of determinism
    // if desired)
    public int GetRandomInt (int minInclusive, int maxExclusive) {
        Random.state = state;
        int randomInt = Random.Range(minInclusive, maxExclusive);
        state = Random.state;
        return randomInt;
    }

}

And a MonoBehaviour to run the test:

public class SeedTest : MonoBehaviour {

    void Start () {
        SeedFactory seedFactory = new SeedFactory(123456789);
        string result = "";
        for (int i = 0; i < 20; i++) {
            result += seedFactory.GetRandomInt(int.MinValue, int.MaxValue) + ", ";
        }
        Debug.Log(result);
    }

}

And the results have all been the same:

Windows Editor:
217814258, 711215697, 1793372675, -1318111305, -513578644, 1776128467, -1503243711, -285471819, -1800526065, -1845985472, -2061970588, 188207569, 1858341351, -1139513088, 2136219157, 1255727479, -2070068486, 459175680, 1151694536, 1232856178, 

Windows Standalone:
217814258, 711215697, 1793372675, -1318111305, -513578644, 1776128467, -1503243711, -285471819, -1800526065, -1845985472, -2061970588, 188207569, 1858341351, -1139513088, 2136219157, 1255727479, -2070068486, 459175680, 1151694536, 1232856178,

macOS Standalone:
217814258, 711215697, 1793372675, -1318111305, -513578644, 1776128467, -1503243711, -285471819, -1800526065, -1845985472, -2061970588, 188207569, 1858341351, -1139513088, 2136219157, 1255727479, -2070068486, 459175680, 1151694536, 1232856178,

Android:
217814258, 711215697, 1793372675, -1318111305, -513578644, 1776128467, -1503243711, -285471819, -1800526065, -1845985472, -2061970588, 188207569, 1858341351, -1139513088, 2136219157, 1255727479, -2070068486, 459175680, 1151694536, 1232856178,
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.