Bizarre FRandomStream Behaviour

I have a dungeon generator C++ class, with a function that gets a random location within the generated dungeon. It does so by getting the center coordinates of a random cell in the dungeon, and offsetting it by the width/height of the cell by a random amount.

Here is a simplified version of the function:

FVector2D AAHRDungeonGenerator::GetRandomLocationInDungeon()
{
    FVector2D   cellLocation = GetRandomCellLocation();
    cellLocation.X += randomStream.FRandRange(-500, 500);
    cellLocation.Y += randomStream.FRandRange(-500, 500);
    return cellLocation;
}

Using Blueprints, I’ve made it so this function runs 10000 times and draws a point at the location returned. This is how that looks ingame:

The pattern that gets produced is strange. The Y offset is behaving as expected, generating dots along the entire height of the cell, but the X offset only deviates a tiny amount.

Noticing that the Y was working perfectly as expected, I tried adding a throwaway FRandomStream call to the function, as shown here:

FVector2D AAHRDungeonGenerator::GetRandomLocationInDungeon()
{
    FVector2D   cellLocation = GetRandomCellLocation();
    float throwawayVariable = randomStream.FRandRange(0, 1);
    cellLocation.X += randomStream.FRandRange(-500, 500);
    cellLocation.Y += randomStream.FRandRange(-500, 500);
    return cellLocation;
}

And, bizarrely, this causes the function to behave perfectly as expected:

So… I’m not really sure what to make of this. It’s like my randomStream property needs to be “primed” with a completely unused call before actually using it for some game logic.

The throwaway variable workaround seems to be working fine for addressing the problem, but obviously it’s really smelly. I’d love to know why FRandomStream doesn’t work the way I thought it would in the first example shown above.

Here are some additional details about the randomStream property in my dungeon generator class, incase they’re relevant:

randomStream Property

The randomStream property is a UPROPERTY that is created in the header file, as shown here (all other properties/functions removed for clarity):

UCLASS()
class HARVESTREMAKE_API AAHRDungeonGenerator : public AActor
{
    GENERATED_BODY()
public:
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
    FRandomStream randomStream = FRandomStream();
}

randomStream runs Initialize() in my GenerateDungeon function, which runs well before the GetRandomLocationInDungeon() function:

void AAHRDungeonGenerator::GenerateDungeon(int seed)
{
    randomStream.Initialize(seed);

    ClearDungeon();
    GenerateRooms();
    GenerateHallways();
    SpawnCells();
    SpawnEnemies(); // This is the function that uses GetRandomLocationInDungeon()
}

Even just a confirmation from someone else that they’ve experienced similar FRandomStream weirdness like this would be somewhat relieving to hear, just so I’m not alone on this.

I was fortunate that this issue presented itself in an obvious way this time around, but I’m worried about it showing up in tremendously more subtle ways in the future.
It could even be occurring right now in the main dungeon generation code, since it uses the same FRandomStream; generated dungeons look fine at a glance, but I can’t tell for certain if any aspect of it is bugged, and similarly needs throwaway variables placed within to make FRandomStream function properly.

Regardless, I’ll only bump once since this isn’t a stop-ship issue. I’m alright if this doesn’t end up getting attention.

Hey Starbladek. We went from using a custom Lehmer randomizer to Unreal’s FRandomStream and haven’t seen any issue like this, sorry.

This might be obvious or not so obvious: Have you changed the seed? Are you using the same seed multiple times? What if you use C++'s built in rand? Does any of that change the outcome?