Dynamic Array suddenly becomes static?

I have created a very simple BlueprintCallable function that returns a TArray of random integers. In my level blueprint I call the function and loop through the TArray and print them on screen to verify that they are actually random.
This works fine in the level editor, but when I package the game the TArray is only filled with random numbers on the first run. On each subsequent run it return the same data every time.

Here is the code.

.h file:



UCLASS()
class AMaze : public AActor
{
	GENERATED_UCLASS_BODY()

public:
	UFUNCTION(BlueprintCallable, Category = "Game")
	static TArray<int32> CreateMaze(int32 Size);

};


.cpp file:



TArray<int32> AMaze::CreateMaze(int32 Size)
{
	TArray<int32> rndwalls;
	for (int x = 0; x < Size; x = x + 1)
	{
		rndwalls.Add(rand()%9);
	}
	return rndwalls;


If I am not mistaken the rand() runs on a seed. So if its the same seed it will be the same result every time. I can’t remember how to change the seed as I have not used rand() in a while but that will probably be the reason why its the same results every time.

Edit: I found this rand - C++ Reference and mentions about using a seed using srand to make it random each run.

That was it! Now it’s random in the packaged game too. Thank you so much!
It still doesn’t explain why the numbers are random in the editor but not in the final build but I’m ok with that as long as it works :slight_smile:

Not sure why it would work in the level editor and not in the packaged game. I am guessing that the srand() was getting set in the level editor somewhere that you don’t know about but not in the packaged game. That is the only logical conclusion I can think of. Either way I am glad it is now working for you. I had a similar problem when I was learning C++ in the past with random numbers and I had to do research to why the output was always the same and never truly random.

Not hijacking the topic but,
I want to know what the term seeded actually means? I found also seeded spawn in cascade modules but I couldn’t understand what they actually do and what it actually means.

The reason why it’s called a seed is because the sequence of random numbers is determined entirely by an initial data point (the seed). It is like an analogy for the growth of a plant. A seed is a tiny object that determines the outcome of what the plant is. A different seed will create a different plant. Random number generation, and indeed all forms of procedural content generation, work this way.

I only just now registered, so I haven’t looked at cascade and cannot address that part of your question.

The random number generator from cstdlib uses a global variable in order to store the initial seed. This implies that any collection of code which uses the library will share that same global seed value.

Without looking at the code, the behavior here is strongly indicative that the editor at some point initializes the seed during its execution. However, the compiled game in contrast might never have modified the seed global variable in contrast, and thus will behave differently.

Relying on cstdlib’s random number generation is bad practice and should generally be avoided. Other C++ libraries can easily interfere with the global seed at any arbitrary and unexpected time, making it unsafe to assume the sequence is reliable. Furthermore, it does not allow you to create multiple separate generators with different seeds, which occasionally can be useful if you want to intentionally store specific generators associated with specific seeds, so that you can compare the results of the different generators (which will always be the same when the seeds are the same), for example.

The cstdlib rand is fine for simple testing purposes, but if you want to use random numbers in any serious way in your game then you should utilize a 3rd party higher quality random generator (many free ones are available) such as the Mersenne Twister or various other algorithms. There’s often a trade off between random number quality and performance, so take some time to figure out what is optimal for your system’s constraints.