RNG Session
Introduction
In a deterministic setting, the output will always be the same given the same input. However, there are some situations where one would want to introduce some randomness to simulate the effects of unpredictable events or to provide some degree of variability to a system. Random number generators, also known as RNG
s, are an important component in achieving this inside of Quantum.
RNGSession
Quantum provides the developer with RNGSession
. This can be used in the simulation to generate pseudorandom numbers deterministically. The frame globals
come preloaded with a global session. A session will ALWAYS produce the same sequence of numbers unless seeded differently.
Usage:
C#
// inside of a system
public override void OnInit(Frame f)
{
int randomNum = f.Global->RngSession.Next(0, 100);
}
The session found in globals
is seeded with the runtime config Seed
field. By default this number will never change. An example on how to set it is as follows:
C#
// inside of unity, prior to starting quantum
public void SetSeed(RuntimeConfig config)
{
// set seed to a random integer
config.Seed = UnityEngine.Random.Range(int.MinValue, int.MaxValue);
}
In Quantum's default scripts, the seed can be set in the UIRoom
script. When running in local debug mode, it can be modified in the QuantumRunnerLocalDebug
script.
Changing Seed at Runtime
If required, the seed can be changed at runtime by overwriting the session with a new one. Example:
C#
// inside of simulation
public void ResetSeed(Frame frame)
{
int newSeed = 100;
frame.Global->RngSession = new Photon.Deterministic.RNGSession(newSeed);
}
This can be useful in some cases, such as frequently resetting the session in order to make the generation even more unpredictable.
Component Usage
In development, it may be favorable to have your RNG on a per-component basis, instead of just using the global session. This could be useful for having each entity behave slightly differently, for example; having plants in a farming game grow at different intervals instead of all at the same time.
C#
// DSL component
component MyComponent
{
RNGSession Session;
}
You can also set the seed in the same way as the global session:
C#
public void InitComponentWithSeed(MyComponent* component)
{
int newSeed = 100;
component->Session = new RNGSession(newSeed);
}
Avoiding Prediction Issues
Having the RNG on a per component basis also guarantees culling will not affect the final positions of predicted entities unless the rollback actually required it.
for more information, see: Avoiding RNG Issues
Cheating
Due to the nature of determinism, predicting randomness is quite trivial. For example, a hacker could read the simulation locally, then duplicate the RNGSession
outside of the simulation and know the given sequence of numbers before anyone else. A common way to combat this is to frequently reset the seed to a number that cannot be easily predicted. For example, you could hash the player's input and use the result as the seed. This makes it very hard for anyone to control OR predict what the seed will be.