Random InitState not working with Coroutines / IEnumerator?

Hi!

When you first start our game, world objects such as houses are instantiated in random positions using a given seed.
The idea was to save the seed, then use Random.InitState(seed) to re-generate the same layout the next time the game is played.

The issue is that it doesn’t seem to work with coroutines.

If I use InitState via FixedUpdate it works as expected, but our prefab instantiation is done via coroutines to prevent the game “freezing” while everything is placed down.

Here’s a quick example script to show the issue.

This code SHOULD give the same 4 numbers each time you click “Run”.

But if you click “Run” a bunch of times and you’ll start to inconsistent results.

using System.Collections;
using UnityEngine;

public class randomTest: MonoBehaviour
{
public bool run = false;
public IEnumerator RandomNumbers()
    {
        int iteration = 0;
        int xIterations = 4;
        Random.InitState(255);
        for (int x = 0; x < xIterations; x++)
        {
            iteration++; 
            Debug.Log(iteration.ToString()+" = "+Random.Range(0,100));
        }
    }

    private void FixedUpdate()
    {
        if(run)
        {
            run = false;
            StartCoroutine("RandomNumbers");
        }
    }
}

I’ve been struggling with this all day. It SHOULD work but simply doesn’t.

My best bet is something to do with timing, but even adding a WaitForFixedUpdate or WaitForEndOfFrame doesn’t seem to help.

Please let me know if you can help!

I’m not sure why, but removing “yield return null” seems to fix this issue.

I have no idea if this is a glitch with coroutines, a timing issue or something else but I guess my issue is solved.
Sadly the whole point of yield was to prevent game “freezes” while instantiating multiple game objects, but I’ll sacrifice it for consistent results.

@HellsPlumber

You need to prevent the Coroutine from running if it’s already running.

Try adding an _isRunning toggle.

    public bool run = false;
    private bool _isRunning = false;

    public IEnumerator RandomNumbers()
    {
        int iteration = 0;
        int xIterations = 4;
        Random.InitState(255);
        for (int x = 0; x < xIterations; x++)
        {
            iteration++; 
            Debug.Log(iteration.ToString()+" = "+Random.Range(0,100));
            yield return null;
        }
        _isRunning = false;
    }
 
    private void FixedUpdate()
    {
        if(run && !_isRunning)
        {
            run = false;
            _isRunning = true;
            StartCoroutine("RandomNumbers");
        }
    }