- Home /
System.Random() with seed not matching .Net or mono
I am scripting my Unity code in c# and using System.Random() with a seed to generate predictable letters for my game. I am doing the same thing on a server written in c# using .NET and was expecting the numbers to match up.
However I am getting two separate predictable results for example Unity outputs:
94 92 67
with code:
System.Random rnd = new System.Random( 8675309 );
Debug.Log( rnd.Next( 100 ) );
Debug.Log( rnd.Next( 100 ) );
Debug.Log( rnd.Next( 100 ) );
The c# server outputs:
75 99 57
with code:
System.Random rnd = new System.Random( 8675309 );
Console.WriteLine( rnd.Next( 100 ) );
Console.WriteLine( rnd.Next( 100 ) );
Console.WriteLine( rnd.Next( 100 ) );
I downloaded MonoDevelop 3.0.6 to run the server and obtained the same random numbers. I also tried running the server in dot net 3.5 and 4.0 with the same results.
I was under the impression that Unity was running under Mono and I should obtain my expected results.
Does anybody know whats going on? I am using Linq in my Unity code so I know the dot.net api has to be version 3.5 or higher.
Why are you not just using the ordinary Random toutines that Unity supplies you with?
(1) do not use System.Random, just use this http://docs.unity3d.com/Documentation/ScriptReference/Random.Range.html
(2) it has been true for some TWENTY YEARS that you should generally speaking never use, look at, know about, or be involved with "seed" when getting a random number for a game. it has absolutely no relationship to anything, unless you know everything there is to know about random numbers and systems program$$anonymous$$g.
1) Because UnityEngine.Random only has one universal seed. System.Random can have different seeds for different sequences.
2) Totally false, you need to set seeds for repeatable sequences of pseudo-random numbers. This is really really commonplace; why do you think all random number generators have this ability?
Answer by Eric5h5 · Feb 05, 2013 at 01:06 AM
MonoDevelop is a code editor, not something that Unity runs under; presumably you're talking about Mono. System.Random results with a seed are not even 100% guaranteed between versions in .NET, never mind between .NET and Mono. To get 100% predictable results across platforms you will need to write your own pseudo-random generator.
Yes, most documentations of program$$anonymous$$g languages usually warn you to not use their random generator for encryption or things like that since the implementation could by changed at anytime.
Thanks for the advice. I was expecting this to be a bit more standard then it appears it is. Will have to come up with my own generator or find one that does what I need.
Answer by Bunny83 · Feb 05, 2013 at 01:29 AM
The simplest pseudo random generator i know is the one that comes with borland pascal. It works pretty well. I've never tried the implementation in C#, but it in general it should work.
Here's a quick adaption of the generator:
// C#
public class MyRandom
{
private int m_Value = 0;
public MyRandom(){}
public MyRandom(int aSeed)
{
m_Value = aSeed;
}
private int Next()
{
m_Value = m_Value * 0x08088405 + 1;
return m_Value;
}
public int Range(int aMin, int aMax)
{
return aMin + Next() % (aMax-aMin);
}
}
Haven't tried this implementation but it should work (unless C# complains about integer overflow ;)).
ps: it's of course just a 32 bit random generator, but if i don't used the wrong multiplier it shouldn't repeat within the 32 bit limit. So it reapeats exactly after 0xFFFFFFFF times.
Thanks for the code, may end up using this or something like it to solve my problem.
Answer by VoidYTMain · Nov 27, 2016 at 02:57 PM
It just System.Random
namespace Game.Maze
{
public class SystemRandomAdaptor : IRandom
{
private readonly int[] SeedArray = new int[56];
private int inext;
private int inextp;
public SystemRandomAdaptor(int seed)
{
int num1 = 161803398 - System.Math.Abs(seed);
SeedArray[55] = num1;
int num2 = 1;
for (int index1 = 1; index1 < 55; ++index1)
{
int index2 = 21 * index1 % 55;
SeedArray[index2] = num2;
num2 = num1 - num2;
if (num2 < 0)
num2 += int.MaxValue;
num1 = SeedArray[index2];
}
for (int index1 = 1; index1 < 5; ++index1)
{
for (int index2 = 1; index2 < 56; ++index2)
{
SeedArray[index2] -= SeedArray[1 + (index2 + 30) % 55];
if (SeedArray[index2] < 0)
SeedArray[index2] += int.MaxValue;
}
}
inext = 0;
inextp = 21;
}
protected virtual double Sample()
{
return InternalSample() * 4.6566128752458E-10;
}
private int InternalSample()
{
int num1 = inext;
int num2 = inextp;
int index1;
if ((index1 = num1 + 1) >= 56)
index1 = 1;
int index2;
if ((index2 = num2 + 1) >= 56)
index2 = 1;
int num3 = SeedArray[index1] - SeedArray[index2];
if (num3 < 0)
num3 += int.MaxValue;
SeedArray[index1] = num3;
inext = index1;
inextp = index2;
return num3;
}
private double GetSampleForLargeRange()
{
int num = InternalSample();
if (InternalSample() % 2 == 0)
num = -num;
return (num + 2147483646.0) / 4294967293.0;
}
public SystemRandomAdaptor(long seed) : this((int)seed) { }
public int Random(int min, int max)
{
max += 1;
long num = max - (long)min;
if (num <= int.MaxValue)
return (int)(Sample() * num) + min;
return (int)((long)(GetSampleForLargeRange() * num) + min);
}
}
}
,It just using System.Random code
namespace Game.Maze
{
public class SystemRandomAdaptor : IRandom
{
private readonly int[] SeedArray = new int[56];
private int inext;
private int inextp;
public SystemRandomAdaptor(int seed)
{
int num1 = 161803398 - System.Math.Abs(seed);
SeedArray[55] = num1;
int num2 = 1;
for (int index1 = 1; index1 < 55; ++index1)
{
int index2 = 21 * index1 % 55;
SeedArray[index2] = num2;
num2 = num1 - num2;
if (num2 < 0)
num2 += int.MaxValue;
num1 = SeedArray[index2];
}
for (int index1 = 1; index1 < 5; ++index1)
{
for (int index2 = 1; index2 < 56; ++index2)
{
SeedArray[index2] -= SeedArray[1 + (index2 + 30) % 55];
if (SeedArray[index2] < 0)
SeedArray[index2] += int.MaxValue;
}
}
inext = 0;
inextp = 21;
}
protected virtual double Sample()
{
return InternalSample() * 4.6566128752458E-10;
}
private int InternalSample()
{
int num1 = inext;
int num2 = inextp;
int index1;
if ((index1 = num1 + 1) >= 56)
index1 = 1;
int index2;
if ((index2 = num2 + 1) >= 56)
index2 = 1;
int num3 = SeedArray[index1] - SeedArray[index2];
if (num3 < 0)
num3 += int.MaxValue;
SeedArray[index1] = num3;
inext = index1;
inextp = index2;
return num3;
}
private double GetSampleForLargeRange()
{
int num = InternalSample();
if (InternalSample() % 2 == 0)
num = -num;
return (num + 2147483646.0) / 4294967293.0;
}
public SystemRandomAdaptor(long seed) : this((int)seed) { }
public int Random(int min, int max)
{
max += 1;
long num = max - (long)min;
if (num <= int.MaxValue)
return (int)(Sample() * num) + min;
return (int)((long)(GetSampleForLargeRange() * num) + min);
}
}
}
Your answer
Follow this Question
Related Questions
Enemy AI move random. 1 Answer
Locked icon in Mono develop 0 Answers
i need help with a random number health script 2 Answers
Unique # Generation "Cannot cast from source type to destination type." 3 Answers
Semi Random Monster Spawner 3 Answers