Questions about changes to UnityEngine.Random. Random.Seed deprecated

Previously, I’ve been using PlayerPrefs to store an integer from Random.seed to save the level and restore the integer from PlayerPrefs to Random.seed to restore the level.

The code to save the seed.

PlayerPrefs.SetInt("Seed",  Random.seed);
PlayerPrefs.Save();

The code to restore the seed.

if (PlayerPrefs.HasKey("Seed"))
{
    Random.seed = PlayerPrefs.GetInt("Seed");
}

Recently, however, Random.seed has been deprecated and replaced with Static Variable Random.state and Static Function Random.InitState.

Now I changed my restore code to look like this

if (PlayerPrefs.HasKey("Seed"))
{
    //Random.seed = PlayerPrefs.GetInt("Seed");
    Random.InitState(PlayerPrefs.GetInt("Seed"));
}

and that seems like a simple enough change and seems to work the same as before.

However Random.state does not return an Int. I think maybe it returns it’s own data type of Random.State? If that’s correct, then I don’t know what to do with that to store it. I don’t know how to display it either. I find it useful to use Debug.log to display the value from Random.seed so I know if the sequence is changing when it’s not supposed to be.

I’ve read Unity - Scripting API: Random.state and I see that I can store a Random.state to a variable of type Random.State, but that doesn’t help me display it for debug purposes, and I’ll basically have to write my own class to store and recall data from the disk just to be able to handle it.

Does anyone know why Unity made these changes? Does anyone know what the benefit is. Is there some central location where these changes are discussed that I can go to?

The Unity seed thing is bad practice. First there were changes over how it works, the entropy, and how many ints you needed to restore it, but it is also used by your entire project. If for any reason you get any random number anywhere during your re-generation of the level, you will completely change the outcome.

Simply use the C# System.Random library.

It allows you to create a Random object using a seed, and to easily get numbers in any range. Simply store that object in a static var or a singleton, and use it for every procedural generation script.

You will have to create extensions to the class to be able to save and load the random object in a string.

http://stackoverflow.com/questions/19512210/how-to-save-the-state-of-a-random-generator-in-c

They have deprecated the “seed” because if actually never allowed to restore the state of the Random generator. The seed never changed while producing random numbers. So storing and restoring the seed doesn’t actually bring back the last state of the generator but just let it produce the same numbers again.

Now with Random.state you can actually store the current state and restore it. However the state has more variables than a single int. It actually has 4 ints. That’s why the State struct looks like this:

[Serializable]
public struct State
{
	[SerializeField]
	private int s0;
	[SerializeField]
	private int s1;
	[SerializeField]
	private int s2;
	[SerializeField]
	private int s3;
}

I don’t get why they made the fields private …
However since the struct as well as the fields are serializable you can use Unity’s JsonUtility to serialize it and to restore the State object from a json string.

So if you want to use PlayerPrefs you would need to change your “int” into a “string” and store the serialized json

It might be useful if the added some State.ToText State.FromText

Right now I have to do this

Debug.Log(JsonUtility.ToJson(UnityEngine.Random.state));

and later

UnityEngine.Random.state = JsonUtility.FromJson<UnityEngine.Random.State>("{ \"s0\":-882691893,\"s1\":439609903,\"s2\":-186639039,\"s3\":586293905}");

When finding bugs for randomly generated stuff.