Rand() gets seeded with a compile time constant in Shipping builds

I would like to report a bug for an issue that has already been described in another question at Random numbers in Blueprint - Blueprint - Epic Developer Community Forums.

rand() produces pseudo-random numbers just fine in Debug and Development builds in the UE Editor, but it seems like UE passes a compile time constant to srand() in Shipping builds which lead into rand() no longer producing pseudo-random, but rather totally deterministic numbers.
It doesn’t seem to be needed to call srand() ourselves in Debug/Development builds - rand() will even work fine without it, so apparently UE seed it properly during initialization in those configurations, but even if I explicitly set a proper seed myself for example in the constructor of a custom C++ class attached to an actor, that does not help for Shipping builds, as UE apparently overrides that seed with a compile time constant value at a later stage.

This even happens for Epics own demos, when running Shipping builds of them and leads to rather funny results:

Hi Kaiserludi,

What rand() function are you using and where are you using it? Also, have you tried using a FRandomStream to do your random generation as the people in the post that you’re referencing did? It seems like that was the solution to the issue that they were encountering. You can find more information about the functions inherent to FRandomStream here:

I’ll be looking at the Blackjack project to look into this issue further in the meantime.

Hi .

I am talking about the standard library rand() (http://www.cplusplus.com/reference/cstdlib/rand/).

No, I have not tried FRandomStream.
It seems inappropriate for our usage, as the documentation that you have linked explicitly states “Very bad quality in the lower bits. Don’t use the modulus (%) operator.”, which unfortunately is exactly what we do with the random values.

This is not blocking us, as although it doesn’t work if we call srand() in the constructor, it works, I we call it later in BeginPlay() (I assume that UE itself is calling srand() at some point in time between those two, so that it overrides the seed that we set in the constructor, but that the seed from BeginPlay() overrides the one that has been set by UE).

Hello Kaiserludi,

While looking back at fixes that have been made surrounding this issue, it seems like this issue was fixed shortly after 4.8.3’s release, meaning it should be working in 4.9 Preview. Could you give it a try there and see if you get the same issue? I wasn’t able to get it to happen with the Blackjack project but I wasn’t able to repro it previously either.