0

I am trying to access random elements from an array, but the Random generator that I am using keeps on giving me numbers in order like so:

Ordered Random

The numbers will always come out sequenced, never completely random (ie. the next number is always greater until the max is reached, then starts from low numbers again). This can be incremental or decremental as well.

I am using a seeded Random object and Random.Next(-100, 100). This is not the same as the behaviour demonstrated on the MSDN Random.Next page

All I can think of is that the version of .Net packaged with Unity does not have the most recent Random? Any solutions to this confusion?

//Example
//Seed and ods set before the Awake method is called
public int seed;
public GameObject[] pathPartOds;

Random random;
GameObject[] path;

void Awake () 
{
    random = new Random (seed);
}

void CreatePath (int length) 
{
    path = new GameObject[length];

    for (int i = 0; i < length; i++)
        path[i] = pathPartOds[random.Next (0, pathPartOds.length)];
}

Have used multiple seeds and they all give the same result, and I have been creating seeds using a random int

Jonas
  • 121,568
  • 97
  • 310
  • 388
Alexis R
  • 61
  • 1
  • 7
  • 4
    Can you show _your_ code - how/when are you seeding it etc? Once or multiple times? – James Thorpe Mar 03 '16 at 10:03
  • 1
    Are you creating a new instace of `Random` every time? – Jcl Mar 03 '16 at 10:06
  • Check already answered questions http://stackoverflow.com/questions/1785744/how-do-i-seed-a-random-class-to-avoid-getting-duplicate-random-values http://stackoverflow.com/questions/4060961/seeding-a-pseudo-random-number-generator-in-c-sharp – xxxmatko Mar 03 '16 at 10:07
  • @Jcl: I bet lunch on that. – Bathsheba Mar 03 '16 at 10:08
  • @Bathsheba not calling, I'd lose ;-) – Jcl Mar 03 '16 at 10:09
  • Could you provide the Seed you are using? – Marcel B Mar 03 '16 at 10:21
  • @JamesThorpe Have added the code, only seeding once – Alexis R Mar 03 '16 at 21:41
  • @Jcl Only creating the one cached instance of Random – Alexis R Mar 03 '16 at 21:42
  • @JoeBlow Sorry, I need to use a System.Random so that the path can be the same every time the same seed is used. Using Unity Random will generate completely random results every time. – Alexis R Mar 03 '16 at 21:45
  • @AlexisR does it happen with any seed? Maybe you just used an unfortunate seed? – Jcl Mar 03 '16 at 21:49
  • I don't see any outputs to the log in the code you posted, How do you output the numbers you get for the result? – Scott Chamberlain Mar 03 '16 at 21:54
  • @ScottChamberlain These are just examples sorry, but the point of it is that I am using a cached and seeded Random, the snap I took of the console is when I tested with random.Next (-100, 100) to try and produce results similar to the MSDN site – Alexis R Mar 03 '16 at 22:01
  • And I think your test was flawed. Please post a example of the source code of a test that shows random is outputting like you say it is. – Scott Chamberlain Mar 03 '16 at 22:02
  • @AlexisR you are NOT actually showing your code which prints the Debug line so you can't be helped here. I can think of 1000 things which may have gone wrong; for example how many objects is this `MonoBehaviour` sitting on? – Fattie Mar 03 '16 at 22:03
  • Okay, will post the exact code when I get home, thanks so far guys. But it is only from one ScriptableObject – Alexis R Mar 03 '16 at 22:07
  • @JoeBlow Sorry, never got around to posting the rest of the code. I did however solve the issue, the Random object was accessed elsewhere from a parent class not involved in the same operation, which of course altered the output. – Alexis R Mar 08 '16 at 01:46

1 Answers1

1

You need to create an instance of Random exactly once and pass that as a parameter into your function that draws a random number.

Else you'll ruin the generator's statistical properties due to it being seeded in a systematic (i.e. non-random) way. That explains the piecewise monotonicity of your output.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • also, be aware that you need to avoid calling `Next` (and every other method) on the same instance from multiple thread at the same time (use a `lock(myRandom)` or something similar) – Gian Paolo Mar 03 '16 at 10:12
  • Yep, and creating two `Random` objects from two different threads at about the same time (using the default constructor) can lead to having the same seed on them so the `Next` sequence is identical per-thread. I have a utility static method (with proper locking) that returns a `Random` object... the first time it's called it uses `Environment.TickCount` as a seed, and then it'll store the first number in the sequence (using `Next`) as the seed for subsequent instances. It works pretty fine and it's quite independent of time, even if you create many instances of `Random` at the same time – Jcl Mar 03 '16 at 10:22
  • Outrageous plug of my beautiful answer http://stackoverflow.com/questions/35701716/random-generates-number-1-more-than-90-of-times-in-parallel/35701778#35701778. – Bathsheba Mar 03 '16 at 10:28
  • @Bathsheba reading your answer... I'd almost always prefer to have one `Random` per-thread (assuming you ensure you don't get the same seed on every instance, as I explained above), so that `Next` doesn't need locking (I lock on the instance creation/storage of the next seed, but not on `Next`, which I'm almost always calling many times)... do you see anything wrong with this approach? – Jcl Mar 03 '16 at 10:32
  • @Jcl: I'm not an expert on the C# random generator, but in the C++ world that is certainly error-prone and I suspect that C# would be no better. Your seeds might not give disjoint sequences which would be a disaster from a statistical perspective. The Mersenne Twister of the C++ standard library allows you to effectively fast-forward the generator to a certain point. You then launch your parallel threads starting at different points. That's what we do in parallel Monte Carlo simulations when pricing derivatives etc. – Bathsheba Mar 03 '16 at 10:34
  • @Bathsheba I see... never used random for any analytical stuff. [This](https://dotnetfiddle.net/tmjskc) (based on the question of your beautiful answer ;-) ) is basically what I'm doing. I'd probably not do this on a situation like this one since it'd be a memory hog (I lowered the iterations for dotnetfiddle), but seems to produce a correct distribution, I'd say, and for most situations where I use random (which frankly, are not a lot ;-) ) enough. I guess if I used it more I could just lock on `Next` and use just one instance for all threads :-) – Jcl Mar 03 '16 at 10:43
  • 1
    I think that code is problematic. There's no guarantee that the sequences will be disjoint. If you have time, try running it through the *diehard* test for statistical randomness. Methinks it will fail the autocorrelation checks. – Bathsheba Mar 03 '16 at 10:51
  • @Bathsheba interesting, will do! Thanks! – Jcl Mar 03 '16 at 10:52
  • 1
    @Bathsheba I just wrote a test and ran the [diehard test suite](http://stat.fsu.edu/pub/diehard/) with a 4000M uint dataset generated with that same routine (one Random instance per thread, each thread writes 10000 ints), and I'd say it passes all 15 tests quite correctly (p-values scattered, and not consistently near 0 or 1). Any specific test I should look for? (sorry, probably SO comments not being the best place to discuss this? :/ ) – Jcl Mar 03 '16 at 11:55
  • Well done for running the diehard tests! Hardcode the seeding to sort of statically simulate what C# does by default. Contrive it in such a way that you *get* non-disjoint drawings. It seems that you've been luckly. – Bathsheba Mar 03 '16 at 11:58
  • I'll take a shot when I have some free time, I have spent more than I can on this during my work time, gee ;-). Thanks, this is all pretty interesting – Jcl Mar 03 '16 at 12:01
  • @Bathsheba just in case you are interested, [here's the output](http://pastebin.com/m2AU5Z4U) – Jcl Mar 03 '16 at 12:05
  • you are not ***actually showing your code which prints the Debug line*** so you can't be hlkped here – Fattie Mar 03 '16 at 21:58
  • Guys ***UNITY HAS ONLY ONE THREAD***, what are you talking about threads? it is exceptionally unlikely that is the problem – Fattie Mar 03 '16 at 22:00
  • it's true that of course the code "fragment" shown in the answer, could be being called more than once - or whatever - the question is totally unanswerable as it stands. – Fattie Mar 03 '16 at 22:01
  • hi @Bathsheba . For the record I absolutely do not understand your answer here. What does this mean *create an instance of Random exactly once and pass that as a parameter into your function that draws a random number"*. OP is indeed only creating one new "Random" (called `random`). then - as far as we can tell from the code given - uses that variable in a loop of length `length`. Please help me understand what you are referring to. – Fattie Mar 03 '16 at 22:08