UnityEngine.Random VS System.Random

GDT Random cover

“To be or not be, UnityEngine.Random vs System.Random, that is the question!”.

This is a dilemma as powerful as Shakespeare’s one!

From what I know, Microsoft arrived first with System.Random, therefore Unity loses, end of the article, bye…

Just joking, please wait, maybe Unity is not mad at all, maybe, there is a reason behind the decision of creating another version of the Random object.

We need to investigate, I’m pretty sure, me and you, we will solve the case better than Sherlock Holmes and Watson.

Every case starts from the beginning, so let’s go back to understand some information about this special number.

What is a random number or better a pseudo-random?

Random number

We can think of a random number, in an easy way, as a number generated casually from a range of possible candidates.

Do you remember the dice game? I am not crazy trust me and I don’t wanna play right now, but this is a great example.

A dice has 6 faces and each face has a number from 1 to 6. The goal of the game is to think of a number from 1 to 6, shake the dice and throw it. When the dice stops if the visible number is the same you thought you win.

That number is a random number.

What is that strange word “pseudo”? It’s not a sci-fi or a horror word, it’s just an important adjective to say that in computer programs, our world, these numbers are generated with some algorithms and they are not casual at all.

Everyone knows that developers are the funniest guys in the world and they like to trick us, well, here they made another joke!

They could not create real random numbers so they created a way to generate numbers with algorithms influenced by multiple variables like time, computer performance etc…

So pseudo is the opposite of genuine and they just pretend to provide us random numbers! But we like them anyway and the pseudo-random numbers are enough for our aim!

UnityEngine.Random

Single random generator

If you need a recap about Unity and what a game engine is please have a look at our article “What is a game engine and how does it work?

Unity provides a static class to generate random numbers, it means you don’t have to instantiate an object in your code to use it. Just use this class and its methods to generate the kind of numbers you need for your game.

Let’s see some practical examples:

Load one of the hundred levels to test our incredible game:

//Pick a level randomly
int currentLevel = UnityEngine.Random.Range(0, 100);
//Load level, (a custom method to do it)
LoadLevel(currentLevel);

Please check here for the full documentation about it:

https://docs.unity3d.com/ScriptReference/Random.html

System.Random

Multiple random generator

This is the class provided by C# language and Unity just inherited it with the whole coding language. In this case you need to instantiate an object and use it similarly to Unity and generate random numbers in your game.

Let’s see the same example before:

Load one of the hundred levels to test our incredible game:

//Instantiate System Random object
System.Random random = new System.Random();
//Pick a level randomly
int systemCurrentLevel = random.Next(0, 100);
//Load level, (a custom method to do it)
LoadLevel(systemCurrentLevel);

Please check here for the full documentation about it:

https://docs.microsoft.com/en-us/dotnet/api/system.random

The power of the “Seed”

What is the seed

Before getting into the thick of it, we need to examine one last clue.

Either UnityEngine.Random or System.Random provides this mysterious parameter with their Random class. Is it a kind of secret weapon? Yes it is!

As we said before here we are talking about pseudo-random numbers and they are generated by an algorithm that needs an input to start generating something randomly. This input is called seed.

If we don’t specify this input both classes provide one by themselves, mostly based on time and cpu clock or whatever! In this way this input is always different and the output will be different too!

But what’s interesting is, setting the seed, we can replicate the same sequence of the random twice. Amazing right?

Still doubts? Let me give you an example:

Imagine generating  5 consecutive obstacles in our game, we have 3 different types of obstacles (tree, paddle, stone) and the random sequence generated in a match is paddle, paddle, tree, stone, tree.

We play this match and we believe that this is an incredible sequence of obstacles to face in our game. Then we realise that we generated randomly and we forgot completely how the sequence was.

With 5 it’s easy, but with hundreds? Or thousands?

If we give a seed to the Random object we can reproduce exactly the same sequence forever. What funny guys, those developers, I knew they were clever!

Let’s have a look at the snippet of the example described.

//Our obstacles
enum Obstacle
{
    Tree = 0,
    Paddle = 1,
    Stone = 2
}

public class RandomTest : MonoBehaviour
{
    void Start()
    {
        //Create a seed
        int seed = 23;
        //Set a seed in the Random Generator
        UnityEngine.Random.InitState(seed);
        /* System.Random version
         * System.Random random = new System.Random(seed);
         */
        //Iterate 5 times to generate 5 obstacle
        for (int i = 0; i < 5; i++)
        {
            //Generate randomly an obstacle
            Obstacle obstacle = (Obstacle) UnityEngine.Random.Range(0, 2);
            /* System.Random version
             * Obstacle obstacle = (Obstacle)random.Next(0, 2);
             */
            //Add obstacle to our game (custom method)
            add(obstacle);
            
        }
        Debug.Log("===============END===================");

    }
    //Custom method to add our obstacle, here we just log each obstacle
    void add(Obstacle obstacle)
    {
        Debug.Log(string.Format("Adding {0}", obstacle));
    }
}

Running the snippet above multiple times you will notice in the console that the sequence of our obstacles will be always the same! Why don’t you try it yourself? I challenge you 😉

UnityEngine.Random vs System.Random: What’s the difference?

Difference between unity and system random

We made a long journey, it’s almost time to end it and there are so many things still to see, but now we can tell the difference between these two classes. Well there are just 2 big differences:

  • UnityEngine.Random is a static class, so we will have just one generator of random numbers per match.
    With System.Random you have to instantiate at least one, or you can instantiate multiple Random generators with different seeds at the same time.
  • UnityEngine.Random exposes methods helpful for its context (Unity), let me explain better, in Unity you will play a lot with Vectors to change the position of an object for instance, well UnityEngine.Random can give you a random position inside a circle with Random.insideUnitCircle and the result is already a Vector!

I think now we can in the end answer the definitive question…

When to use UnityEngine.Random or System.Random in a game? 

When use unity random or system random

Well done my friend, we did it, now we know what are these 2 classes and we can say loud and clear when it is better to use one or another:

UnityEngine.Random

  • Use it as the main random generator for the game, it’s easy to use, you don’t have to instantiate anything.

System.Random

  • If you have events in your game and you don’t want to influence the random generation of one with the other one you need 2 random generators, with System.Random you can do it.

I want to clarify the previous explanation with an example:

Imagine we are creating an adventure game and we use a random generator for:

  • A random timer for a bomb explosion.
  • A random chance to find a loot in a box.

And we have 2 actions to fire the events above:

  • Pressing the fire button the player launches a bomb and the bomb script generates a random timer for the explosion.
  • Destroying a box the box script generates a random chance to obtain a loot.

What happens if the player launches 0 or 100 bombs before opening the box?

Using UnityEngine.Random the loot chance will be influenced by the number of times the player launches a bomb.

If the user launches 10 bombs before destroying a box, it means the random generator has been already generated 10 random numbers and the random number associated to the box will be the 11th. 

The 2 events are connected by the random generation and the chance to obtain a loot will be always different runtime due to the gameplay.

In this way we can’t control the experience of a player, making the test of our game extremely difficult.

If we want to avoid a random generation connection with 2 events we need to use System.Random.

Performance

There is no restriction on using UnityEngine.Random or System.Random generators, but there is an important warning from the System.Random documentation:

  • Avoid instantiating multiple times if not necessary because instantiating and initialising a random number generator is a relatively expensive process.

Some good advice could be to instantiate the System.Random during a loading time, of a level or of the game for example, in this way you will avoid to stress the CPU in game.

Conclusion

Here we are, now we know what to do depending on our needs:

  • If we don’t mind in any way how the random generations influence our game we choose UnityEngine.Random, it’s easy, made for Unity and not too expensive in terms of performance.
  • When we want to control the random generation of the game with a seed, but we don’t have in any case connected events influenced by the random generation let’s use UnityEngine.Random.
  • If we have events connected by a random generation, maybe we need to consider if we can have better control of the game experience using different System.Random generators keeping in mind the performance impact for each initialization.

So no “UnityEngine.Random or System.Random” anymore! The case is closed, it was difficult at the beginning, but with the right clues we finally solved the mystery.

What a wonderful team we are!

I think we can solve many cases together, let’s get in touch, the next case is around the corner!

More from Romeo Violini

What is a game engine and how does it work?

If you like video games and you thought about what is behind...
Read More

2 Comments

  • You can also use Unity’s Random.state to save and restore the state if need separate repeatable random number generators. If you need many lightweight random number generators the math.Random in the unity math package used for DOTS stack is designed specifically for that purpose. You would not want to use them for high-quality Monte-Carlo simulations, but they are fast and cheap enough to instantiate hundreds if needed.

Leave a Reply

Your email address will not be published. Required fields are marked *