Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
6
Question by Fragmental · Mar 14, 2017 at 09:01 AM · randomplayerprefssavingrandom.rangeseed

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 https://docs.unity3d.com/ScriptReference/Random-state.html 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?

Comment
Add comment · Show 4
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image tanoshimi · Mar 14, 2017 at 09:18 AM 0
Share

Good question. I wasn't even aware that Random.seed was deprecated - what version of Unity are you using?

Also the docs seem far from helpful: stating that the RNG state can be set either by seed or by explicitly using RandomState but the "effects are quite different", followed by a code listing that appears to demonstrate that the effects are in fact identical!

https://docs.unity3d.com/ScriptReference/Random-state.html

avatar image Fragmental tanoshimi · Mar 14, 2017 at 10:52 AM 0
Share

I'm using 5.4.2. I usually keep up to date, but I've been hesitant to update this time, and Random.seed being deprecated is one reason why. I've run into more than a few cases where I felt like the Unity documentation was lacking.

avatar image Bunny83 tanoshimi · Mar 14, 2017 at 12:50 PM 0
Share

The example is missing an important detail which you can only see when you actually run the code and look at the output. Such examples should have the output as a comment next to the line that produces it so you can actually understand what happens without the need of running the code.

The point is that the numbers generated in step 5 and 6 are the same as those generated in step 3 and 4 since the state was reset to that point. Note that setting the seed again would completely reset the generator. That's why 7 and 8 are equal to 1 and 2.

avatar image Fragmental · Mar 14, 2017 at 11:39 AM 0
Share

If you're following this and you saw a notice that I answered my own question and then accepted it, that was a mistake. I was trying to write a comment and I had a moment.

3 Replies

· Add your reply
  • Sort: 
avatar image
5
Best Answer

Answer by Bunny83 · Mar 14, 2017 at 12:42 PM

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

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Fragmental · Mar 14, 2017 at 05:19 PM 1
Share

Wow, both you, @Bunny83, and @ceandros gave really good answers. Thank you. I decided to try using JsonUtility to serialize Random.state and then save it to and restore it from PlayerPrefs, as a string.

After reading the documentation , and some experimentation, this is what I came up with

To save Random.state:

 PlayerPrefs.SetString("SeedJSON",  JsonUtility.ToJson(Random.state));
 PlayerPrefs.Save();

To load Random.state:

 if (PlayerPrefs.Has$$anonymous$$ey("SeedJSON"))
 {
     Random.state = JsonUtility.FromJson<Random.State>(PlayerPrefs.GetString("SeedJSON"));
 }

And it worked flawlessly, and solved a much bigger issue I was having that I haven't yet mentioned.

I was having trouble with Random.Range giving me different numbers, in the sequence, depending on whether I was calling it from a new scene or a scene that was already running. In other words, Random.seed would change even when it wasn't supposed to.

For example if the scene was loaded and the seed was set to "1234", the next seed number after Random.Range was called would be "4321", every single time. However, if the same code was run a second time, in the same scene and the seed was set to "1234" the next seed would inexplicably be "3412". These are fake numbers, but they give an example of how the numbers were changing when they weren't supposed to.

I don't know if my game was always having this issue and I just never noticed, or if it actually started more recently(maybe after Unity changed UnityEngine.Random?).

Using Random.state fixed that issue.

I do think that it makes a lot of sense, with procedural generation, to do what ceandros says. By using System.Random I could have multiple instances of random number generators with one dedicated to procedurally generating the level so it's guaranteed to be consistent and not affected by any other random number generation in other parts of the project.

For now, however, this is working for me, but in the future, if my procedural generation breaks again(as it's done before) I'll reconsider.

avatar image
4

Answer by lgarczyn · Mar 14, 2017 at 12:10 PM

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

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Fragmental · Mar 14, 2017 at 05:14 PM 0
Share

@ceandros Thank you for your excellent answer.

I agree that using System.Random is probably the best option. I read a little about it here and here before posting my question, but I was unsure about it.

From what I understand, if I used System.Random I could use a new random number generation instance specifically for procedurally generating my levels . In that way I don't have to worry about other calls to Random breaking my levels, and I've broken my level generation a bunch of times, in the past. It's kind of fragile using UnityEngine.Random.

For now, I managed to get it functionally working with UnityEngine.Random.state. However, if using UnityEngine.Random causes any more breakages in the future, I am definitely switching.

I'm accepting Bunny83's answer, because it specifically answers the questions I had about why the Unity devs changed UnityEngine.Random and how to get everything working again with the new changes, even though using System.Random is probably the better solution for Procedurally generated levels.

avatar image
0

Answer by koirat · Jun 27, 2018 at 09:03 PM

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.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

71 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Random: When to set the seed ? 1 Answer

How to save a random seed to a playerpref 2 Answers

Having trouble with PlayerPrefs in my script. 1 Answer

Are there any major consequences when using Playerprefs? 0 Answers

Unity built-in seed? 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges