Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Resolved Unity.Mathematics.Random not consistent per seed when called within IEnumerator?

Discussion in 'Scripting' started by Heroshrine, Aug 30, 2023.

  1. Heroshrine

    Heroshrine

    Joined:
    Feb 11, 2018
    Posts:
    13
    Hello all.

    I believe I have discovered a bug, whether that be in my own code or in unity's, or I'm using it improperly.
    I have some code that I am using to generate a level. I am generating the level in a Coroutine. I want to be able to slow this generation down to see it in-action to explain to people what's happening easier. For this I implemented a way to control when my coroutine yields:
    DebugInfoSettings.GenerationSpeed
    . When this is 0, I skip a lot of yields and only hit a few
    yield return null
    s. When it is not 0, I use this value at several points with
    yield return new WaitForSeconds(DebugInfoSettings.GenerationSpeed)
    . When this value is not 0, Unity.Mathematics.Random starts returning different numbers than when it is 0. It seems as if anything above 0 returns the same end result, but 0 returns a different end result. I believe this to mean that somehow
    yield return new WaitForSeconds
    is the culprit.

    Here is the code snipet that it breaks in:

    Code (CSharp):
    1. // remove rooms based on rules
    2. for (int i = 0; i < generationInfo.Side; i++)
    3. {
    4.    for (int j = 0; j < generationInfo.Side; j++)
    5.    {
    6.    byte gnr = GetNeighborCount(i, j);
    7.  
    8.    if ((gnr <= removeRules.LimitLTET || gnr > removeRules.LimitGT) && !(i == generationInfo.Side / 2 && j == generationInfo.Side / 2) && random.NextFloat() <= removeRules.ActionChance && rooms[i, j] != null)
    9.    {
    10.      Object.Destroy(rooms[i, j].gameObject);
    11.      Log($"Destroyed By RemoveRooms: {rooms[i, j]}");
    12.  
    13.      if (debugInfoSettings.GenerationSpeed != 0)
    14.        yield return new WaitForSeconds(debugInfoSettings.GenerationSpeed);
    15.      }
    16.  
    17.      dd.Add(random.state);
    18.    }
    19. }
    Here is a hastebin link to the entire file: https://hastebin.com/share/ecohodijuf.csharp

    I have debugged this by writing to a file whenever I generate a level, writing the random.state whenever it is possibly used. I generated a level while GenerationSpeed was 0, and while it was not 0, then iterated over every number until i found when random was not in the same state. Here is the code I used to save and test the files in case you guys want to see it: https://hastebin.com/share/faginamodo.csharp

    Below I have attached two JSON files (converted to .txt files) created with the debugging class I wrote, file1 is with GenerationSpeed at 0, file2 is with GenerationSpeed at 0.001. Both were generated with a seed of 4. For this instance it broke at 4,439 uses of my random instance. If I run this test again with a seed of 3, it breaks at 5,052 uses instead.

    I am using Unity version 2022.3.7 and Unity.Mathematics version 1.2.6. Any help is appreciated!
     

    Attached Files:

    Last edited: Aug 30, 2023
  2. Spy-Master

    Spy-Master

    Joined:
    Aug 4, 2022
    Posts:
    282
    This could be something as simple as missing array element assignment to null after destruction on L149 and L273.
     
    Bunny83 likes this.
  3. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,524
    You use
    Object.Destroy
    inside your remove rooms loop in like 149 and your loop relies on a null check on array elements. As you hopefully know, Object.Destroy is delayed until the end of the current frame. So when you introduce wait times in between, of course the behaviour will change.

    I just realised Spy-Master just beat me to it... :) Yes, manually setting the array elements to null when you destroy the objects should fix that issue. It's a common Unity gotcha.
     
  4. Heroshrine

    Heroshrine

    Joined:
    Feb 11, 2018
    Posts:
    13
    oh my god I can't believe this is what it was. I must have accidentally undone it because I had it there before, but at one point I undid a lot. Thank you.
     
    Bunny83 likes this.