Search Unity

Strange random seed issue with level generation

Discussion in 'Scripting' started by drjamiearron, Jul 31, 2019.

  1. drjamiearron

    drjamiearron

    Joined:
    Jun 8, 2012
    Posts:
    134
    I am currently working on a game that features random level generation, but have ran into an issue when setting a seed.

    This is how I currently set the seed:

    Code (CSharp):
    1. seed = time.Hour + time.Minute + time.Second + time.Millisecond + 1101077;
    2. UnityEngine.Random.InitState(seed);
    This, for example, returns a value such as 1101356. If I set the seed to this value and generate a level I get the same geometry each and every time, which is fine. However, when I spawn the enemies and background props, there is this strange flip-flop behaviour.

    These are the steps:


    1) PRESS GENERATE WITH SEED 1101356
    -- Geometry is created
    -- Enemies are spawned at random locations
    -- Props are spawned at random locations

    2) PRESS GENERATE AGAIN WITH SEED 1101356
    -- The same geometry is created - as expected
    -- Enemies are spawned, this time at different locations - not expected
    -- Props are spawned, this time at different locations - not expected

    3) PRESS GENERATE AGAIN WITH SEED 1101356
    -- The same geometry is created - as expected
    -- Enemies are spawned, this time at the same locations from Step 1 - not expected
    -- Props are spawned, this time at the same locations from Step 1 - not expected

    4) PRESS GENERATE AGAIN WITH SEED 1101356
    -- The same geometry is created - as expected
    -- Enemies are spawned, this time at the same locations from Step 2 - not expected
    -- Props are spawned, this time at the same locations from Step 2 - not expected

    5) REPEAT STEP 2
    -- Observe the same geometry is created
    -- Observe the enemies and prop placements are swapping between their locations from steps 2 to 4

    At the moment all I can think of is some form of seed issue. Prior to updating to Unity 2019.1.9 (latest at the time) this has never happened before and I was always able to spawn the same level over and over again.

    Any ideas?
     
  2. FlashMuller

    FlashMuller

    Joined:
    Sep 25, 2013
    Posts:
    451
    Have you compared the actual numbers that come out of Random? Just to make sure..
     
  3. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    Are you using coroutines or other delayed call or delegates/unity events during creation process? Looks like your props/enemies are messed up somehow, not unity random. I think so because enemies spawn in place of props and props in place of enemies. If seed would be wrong or random generator would contain errors then there wouldn't be such a coincidence.
     
  4. drjamiearron

    drjamiearron

    Joined:
    Jun 8, 2012
    Posts:
    134
    With some inspiration from your suggestion I managed to solve my problem after some exhaustive testing! It's hard to put into words, so bear with me.

    What I do is take an array of prop objects and shuffle them (Fisher-Yates) and then attempt to spawn them at empty spaces. Whilst this works in principle, I was feeding in the referenced array from within the Unity editor, NOT an instance of it, if that makes sense. Therefore, to fix it, I took the original array and copied it to a new instance which is then shuffled in the same order each and every time.

    Before, the original array (i.e. the one in the inspector) was being shuffled and from within Unity (bearing in mind the game is not running) I could see the inspector was being updated with the new shuffled values. Hence, my enemies and props were being spawned in different places.
     
    schwalmentin and ThySpektre like this.
  5. Steamc0re

    Steamc0re

    Joined:
    Nov 24, 2014
    Posts:
    144
    I am having the exact same problem. I found this thread searching for "Random.Init only works once".
    I am doing a marching cubes generation on a level, then instantiating terrain objects on the surface.
    The marching cubes (Random for the voxel array) is the same every time. The terrain objects (trees, rocks) are the same type and position the first time, then DIFFERENT the second time. Every subsequent generation that starts with Random.Init() matches the second.
    I am copying the objects from a ScriptableObject that has a List of objects (the catalog as it were) to a new List at runtime, based on factors like surface normals and density. The resulting list is all the objects that I can fit onto the terrain and I then go about finding the instantiation positions and rotations for them. This doesn't sound like your problem. From your solution, I can't tell what I should be doing to fix this. I even changed all my foreach to for thinking maybe order was not being preserved. No dice.
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,752
    You should prove that the order really IS being preserved, eg, use Debug.Log() to show that the order on each subsequent run is identical.

    Once that is proven you can cross it off your list of possible issues.

    And you should also definitely start a new thread (it's FREE!) that thoroughly describes any further problem you have, rather than piggyback on what you even suspect is an unrelated problem.

    How to report your problem productively in the Unity3D forums:

    http://plbm.com/?p=220
     
  7. Steamc0re

    Steamc0re

    Joined:
    Nov 24, 2014
    Posts:
    144
    OP was sufficiently related to my issue. It turns out the culprit was a calculation of the bounds of the terrain collider to determine the density of terrain objects; even when reset to original values, rounding errors gave different results.
     
  8. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,752
    There was also a bunch of chatter in another thread this past week about floating point not being deterministic between different CPU architectures. Determinism is like proving a chain of custody: any interruption at any stage along the way breaks its validity.
     
    Steamc0re likes this.