English | 日本語
Random Extensions is a library that provides functionality for pseudorandom number generation for .NET and Unity.
.NET has a built-in Random
class, but it is not sufficient in terms of functionality and contains complex implementations and unnecessary abstractions due to compatibility issues.
Unity's UnityEngine.Random
is a static class, making it impossible to instantiate. Additionally, it manages internal states, making it difficult to reproduce random numbers.
Random Extensions introduces IRandom
as a new abstraction layer for random number generation, providing high performance implementations based on various algorithms (xoshift, xoshiro, splitmix, PCG). It also offers many useful features for handling random numbers, such as extension methods that support System.Numerics
and Unity types, IWeightedCollection<T>
for handling weighted random numbers, and LINQ extensions for random numbers (RandomEnumerable
).
Warning
Do not use this library for security purposes. If you need cryptographically secure random numbers, use System.Security.Cryptography.RandomNumberGenerator
.
Random Extensions requires .NET Standard 2.1 or higher. The package is available on NuGet.
dotnet add package RandomEx
Install-Package RandomEx
You can use Random Extensions in Unity by using NugetForUnity. For more details, refer to the Unity section.
You can generate random numbers using RandomEx.Shared
.
using RandomExtensions;
// Get a random value between 0-9
var n = RandomEx.Shared.NextInt(0, 10);
// Get a random boolean value
var flag = RandomEx.Shared.NextBool();
You can also create an instance of IRandom
initialized with a random seed using RandomEx.Create()
.
// Create an instance
var rand = RandomEx.Create();
// Get a random value in the range [0.0, 1.0)
var d = rand.NextDouble();
Warning
Please note that RandomEx.Shared
is thread-safe, but instances created with RandomEx.Create()
or other classes implementing IRandom
are not thread-safe.
Random Extensions supports more types than the standard System.Random
.
var rand = RandomEx.Create();
// int
rand.NextInt(); // [int.MinValue, int.MaxValue]
rand.NextInt(10); // [0, 10)
rand.NextInt(10, 20); // [10, 20)
// uint
rand.NextUInt(); // [0, uint.MaxValue]
rand.NextUInt(10); // [0, 10)
rand.NextUInt(10, 20); // [10, 20)
// long
rand.NextLong(); // [long.MinValue, long.MaxValue]
rand.NextLong(10); // [0, 10)
rand.NextLong(10, 20); // [10, 20)
// ulong
rand.NextULong(); // [0, ulong.MaxValue]
rand.NextULong(10); // [0, 10)
rand.NextULong(10, 20); // [10, 20)
// float
rand.NextFloat(); // [0f, 1f)
rand.NextFloat(10f); // [0f, 10f)
rand.NextFloat(10f, 20f); // [10f, 20f)
// double
rand.NextDouble(); // [0.0, 1.0)
rand.NextDouble(10.0); // [0.0, 10.0)
rand.NextDouble(10.0, 20.0); // [10.0, 20.0)
rand.NextDoubleGaussian(); // Get a random value following a Gaussian distribution with a mean of 0.0 and a standard deviation of 1.0
// byte[], Span<byte>
rand.NextBytes(buffer); // Fill the buffer with random bytes
Additionally, by introducing the extension package, you can use methods that support types in System.Numerics
and Unity. For details, see the sections on System.Numerics and Unity.
You can use the GetItem()
method to retrieve a random element from an array. If you want to retrieve multiple elements at once, use GetItems()
.
var rand = RandomEx.Create();
// Create an array of values
var values = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
// Get a random element
var item = rand.GetItem(values);
// Get 5 random elements (with duplicates)
var items = rand.GetItems(values, 5);
You can also specify weights for each element. The array of weights you pass as an argument must match the number of elements in the original array.
var values = new int[] { 0, 1, 2 };
var weights = new double[] { 1.0, 5.0, 1.0 };
// Retrieve weighted random elements
var item = rand.GetItem(values, weights);
var items = rand.GetItem(values, weights, 5);
You can shuffle the elements of an array using the Shuffle()
method.
var array = new int[] { 0, 1, 2, 3, 4, 5 };
// Shuffle the array elements
rand.Shuffle(array);
This method modifies the array itself. If you need a side-effect-free shuffle, use the following LINQ extension.
Under the RandomExtensions.Linq
namespace, there are LINQ extensions that utilize random numbers.
using System;
using System.Linq;
using RandomExtensions.Linq;
var sequence = Enumerable.Range(0, 100);
// Get a random element
var r = sequence.RandomElement();
// Shuffle the order
foreach (var item in sequence.Shuffle())
{
Console.WriteLine(item);
}
// Create an IEnumerable<T> that yields random values in the range [0, 9] 10 times
foreach (var item in RandomEnumerable.Repeat(0, 10, 10))
{
Console.WriteLine(item);
}
These methods can take an IRandom
instance for random number generation. If not specified, RandomEx.Shared
will be used.
var rand = RandomEx.Create();
// Get elements using the passed rand instance
var r = sequence.RandomElement(rand);
Under the RandomExtensions.Collections
namespace, there are collections that hold weighted elements.
// Interface for a weighted collection
public interface IWeightedCollection<T> : IReadOnlyCollection<WeightedValue<T>>
{
T GetItem<TRandom>(TRandom random) where TRandom : IRandom;
void GetItems<TRandom>(TRandom random, Span<T> destination) where TRandom : IRandom;
}
// Struct representing a weighted element
public readonly record struct WeightedValue<T>(T Value, double Weight);
Below is a sample of using WeightedList<T>
for weighted selection.
// Create a weighted list
var weightedList = new WeightedList<string>();
// Add elements with specified weights
weightedList.Add("Legendary", 0.5f);
weightedList.Add("Epic", 2.5f);
weightedList.Add("Rare", 12f);
weightedList.Add("Uncommon", 25f);
weightedList.Add("Common", 60f);
// Retrieve a weighted random element
var rarity = weightedList.GetItem();
Random Extensions provides IRandom
as an interface for random number generators. By implementing this interface, you can create custom random number generator.
public interface IRandom
{
void InitState(uint seed);
uint NextUInt();
ulong NextULong();
}
Random Extensions provides several IRandom
implementations by default. Below is a list of class names and the pseudorandom number algorithms they use internally.
Class Name | Algorithm |
---|---|
Pcg32Random |
PCG32 (PCG-XSH-RR) |
SplitMix32Random |
splitmix32 |
SplitMix64Random |
splitmix64 |
Xorshift32Random |
xorshift32 |
Xorshift64Random |
xorshift64 |
Xorshift128Random |
xorshift128 |
Xoshiro128StarStarRandom |
xoshiro128** |
Xoshiro256StarStarRandom |
xoshiro256** |
Under the RandomExtensions.Algorithms
namespace, there are implementations of algorithms for generating pseudorandom numbers.
These are structs with minimal state and methods, useful in scenarios where performance is critical or state serialization is required.
Below is a sample using the XorShift32
struct to generate pseudorandom numbers.
using RandomExtensions.Algorithms;
var seed = 123456;
var xorshift = new Xorshift32(seed);
var r = xorshift.Next();
RandomEx.Numerics
package, available on NuGet, provides extensions that support types in System.Numerics
.
dotnet add package RandomEx.Numerics
Install-Package RandomEx.Numerics
After installation, you can use the methods below.
using System.Numerics;
using RandomExtensions;
using RandomExtensions.Numerics;
var rand = RandomEx.Create();
// Vector2
rand.NextVector2();
rand.NextVector2(new Vector2(10f, 10f));
rand.NextVector2(new Vector2(10f, 10f), new Vector2(20f, 20f));
rand.NextVector2Direction(); // Get a random direction vector of length 1
rand.NextVector2InsideCircle(); // Get random point inside a unit circle
// Vector3
rand.NextVector3();
rand.NextVector3(new Vector3(10f, 10f, 10f));
rand.NextVector3(new Vector3(10f, 10f, 10f), new Vector2(20f, 20f, 20f));
rand.NextVector3Direction(); // Get a random direction vector of length 1
rand.NextVector3InsideSphere(); // Get random point inside a unit sphere
// Vector4
rand.NextVector4();
rand.NextVector4(new Vector4(10f, 10f, 10f, 10f));
rand.NextVector4(new Vector4(10f, 10f, 10f, 10f), new Vector2(20f, 20f, 20f, 20f));
// Quaternion
rand.NextQuaternionRotation(); // Get a quaternion representing a random rotation
Random Extensions is available for use in Unity and provides an extension package.
- Unity 2021.3 or higher
-
Install NugetForUnity.
-
Open the NuGet window by selecting
NuGet > Manage NuGet Packages
, search for theRandomEx
package, and install it. -
Open the Package Manager window by selecting
Window > Package Manager
, then click on[+] > Add package from git URL
and enter the following URL:https://github.com/AnnulusGames/RandomExtensions.git?path=src/RandomExtensions.Unity/Assets/RandomExtensions.Unity
Under the RandomExtensions.Unity
namespace, the following extension methods are available for Unity:
using UnityEngine;
using RandomExtensions;
using RandomExtensions.Unity;
var rand = RandomEx.Create();
// Vector2
rand.NextVector2();
rand.NextVector2(new Vector2(10f, 10f));
rand.NextVector2(new Vector2(10f, 10f), new Vector2(20f, 20f));
rand.NextVector2Direction(); // Get a random direction vector of length 1
rand.NextVector2InsideCircle(); // Get random point inside a unit circle
// Vector3
rand.NextVector3();
rand.NextVector3(new Vector3(10f, 10f, 10f));
rand.NextVector3(new Vector3(10f, 10f, 10f), new Vector2(20f, 20f, 20f));
rand.NextVector3Direction(); // Get a random direction vector of length 1
rand.NextVector3InsideSphere(); // Get random point inside a unit sphere
// Vector4
rand.NextVector4();
rand.NextVector4(new Vector4(10f, 10f, 10f, 10f));
rand.NextVector4(new Vector4(10f, 10f, 10f, 10f), new Vector2(20f, 20f, 20f, 20f));
// Quaternion
rand.NextQuaternionRotation(); // Get a quaternion representing a random rotation
// Color
rand.NextColor();
rand.NextColor(new Color(1f, 1f, 1f));
rand.NextColor(new Color(0f, 0f, 0f), new Color(1f, 1f, 1f));
rand.NextColorHSV(0f, 1f, 0f, 1f, 0f, 1f); // Specify HSV range
rand.NextColorHSV(0f, 1f, 0f, 1f, 0f, 1f, 0f, 1f); // Specify HSV and alpha range
This library is released under the MIT License.