├── WeightAlgorithm.cs
├── AbstractRandomProvider.cs
├── WeightAlgorithm.cs.meta
├── WeightedRandom.cs.meta
├── SystemRandomProvider.cs.meta
├── AbstractRandomProvider.cs.meta
├── UnityEngineRandomProvider.cs.meta
├── UnityMathematicsRandomProvider.cs.meta
├── UnityEngineRandomProvider.cs
├── UnityMathematicsRandomProvider.cs
├── SystemRandomProvider.cs
├── README.md
└── WeightedRandom.cs
/WeightAlgorithm.cs:
--------------------------------------------------------------------------------
1 | namespace Subtegral.WeightedRandom
2 | {
3 | public enum WeightAlgorithm
4 | {
5 | FairBiased,
6 | UnfairBiased
7 | }
8 | }
--------------------------------------------------------------------------------
/AbstractRandomProvider.cs:
--------------------------------------------------------------------------------
1 | namespace Subtegral.WeightedRandom
2 | {
3 | public abstract class AbstractRandomProvider
4 | {
5 | protected AbstractRandomProvider() { Construct(); }
6 | public abstract void Construct();
7 | public abstract double GetRandom();
8 |
9 | }
10 | }
--------------------------------------------------------------------------------
/WeightAlgorithm.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6f0ac854e4231e24cb30f361a18358b8
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/WeightedRandom.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4550d6e9c58edfc4a9343516bf2dceac
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/SystemRandomProvider.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: cde3ede59bcac2e47bf9315e9ee180f6
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/AbstractRandomProvider.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2b7563a6173be0943abfcc7b96d66e04
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/UnityEngineRandomProvider.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a7949e73aa06b844bb6aac516195d17a
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/UnityMathematicsRandomProvider.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b317a5fa185a95a47aff8d76bc48f6c7
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/UnityEngineRandomProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 | namespace Subtegral.WeightedRandom
5 | {
6 | public class UnityEngineRandomProvider : AbstractRandomProvider
7 | {
8 | public override void Construct() { }
9 |
10 | public override double GetRandom()
11 | {
12 | return Random.Range(0f, 1f);
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/UnityMathematicsRandomProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using Unity.Mathematics;
4 | namespace Subtegral.WeightedRandom
5 | {
6 | ///
7 | /// Uses SIMD Instructions to calculate
8 | ///
9 | public class UnityMathematicsRandomProvider : AbstractRandomProvider
10 | {
11 | private Random randomCache;
12 | public override void Construct()
13 | {
14 | randomCache = new Random();
15 | }
16 |
17 | public override double GetRandom()
18 | {
19 | return randomCache.NextDouble();
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/SystemRandomProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using System;
4 |
5 | namespace Subtegral.WeightedRandom
6 | {
7 | public class SystemRandomProvider : AbstractRandomProvider
8 | {
9 | private Random randomCache;
10 | public override void Construct()
11 | {
12 | randomCache = new Random();
13 | }
14 |
15 | public override double GetRandom()
16 | {
17 | return randomCache.NextDouble();
18 | }
19 |
20 | public static SystemRandomProvider GetInstance()
21 | {
22 | return new SystemRandomProvider();
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Weighted Randomizer for Unity
2 | Allows you to get generic biased random selections depending on provided weight.
3 |
4 | **Best part of this randomizer is, it doesn't require to provide 100% total.
5 | It auto-calculates weights regarding to your weights.**
6 |
7 | So you can pass _Add->80%-Tremors _Add->70%-Zombies_ in the same total.
8 |
9 | ## Usage
10 | Simple example:
11 | ```c#
12 | WeightedRandom rnd = new WeightedRandom();
13 | rnd.Add(new Ghost(),0.5f);
14 | rnd.Add(new Zombie(),0.3f);
15 |
16 | rnd.Next(); //This will return a biased random result.
17 | ```
18 |
19 | ## Alternative parameters
20 | WeightedRandom uses _System.Random_ and _FairBiased_ algorithm *by default.*
21 |
22 | **You can choose custom options on the constructor.**
23 |
24 | ### WeightAlgorithm
25 | There are two algorithms right now.
26 | - *UnfairBiased:* Provides a larger probability scale but results can be less predictable.
27 | - *FairBiased:* Provides a steady bias and therefor more predictable results.
28 |
29 | ### Weight Providers
30 | Weight providers are basically random api's which have provided by Unity and C#(System) libraries.
31 | - *SystemRandomProvider:* Uses System.Random implementation
32 | - *UnityEngineRandomProvider:* Uses UnityEngine.Random.Range implementation
33 | - *UnityMathematicsRandomProvider:* Uses Unity's new SIMD math library with Unity.Random implementation
34 |
35 | ## TO-DO
36 | - AddRange for multiple queries at once.
37 | - GetInstance() implementation on other providers with _T where:class_
38 |
--------------------------------------------------------------------------------
/WeightedRandom.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System;
4 | namespace Subtegral.WeightedRandom
5 | {
6 | public sealed class WeightedRandom
7 | {
8 | private Dictionary probabiltyTable = new Dictionary();
9 | private List> sortedPair;
10 | private WeightAlgorithm algorithm;
11 | private AbstractRandomProvider randomProvider;
12 |
13 | #region Constructors
14 | public WeightedRandom() : this(new SystemRandomProvider(), WeightAlgorithm.FairBiased) { }
15 | public WeightedRandom(WeightAlgorithm algorithm)
16 | {
17 | randomProvider = new SystemRandomProvider();
18 | this.algorithm = algorithm;
19 | }
20 | public WeightedRandom(AbstractRandomProvider provider) : this(WeightAlgorithm.FairBiased)
21 | {
22 | randomProvider = provider ?? throw new Exception("Random provider is not instantiated.");
23 | }
24 | public WeightedRandom(AbstractRandomProvider provider, WeightAlgorithm algorithm)
25 | {
26 | randomProvider = provider ?? throw new Exception("Random provider is not instantiated.");
27 | this.algorithm = algorithm;
28 | }
29 | #endregion
30 |
31 | public void Add(T val, float probability)
32 | {
33 | probabiltyTable.Add(val, probability);
34 | sortedPair = probabiltyTable.OrderBy(i => i.Value).ToList();
35 | }
36 |
37 | public T Next()
38 | {
39 | if (sortedPair == null || sortedPair.Count == 0)
40 | throw new Exception("No elements added to probability calculation!");
41 |
42 | float totalProbability = sortedPair.Sum(x => x.Value);
43 | double randomValue = randomProvider.GetRandom() * totalProbability;
44 | for (var i = 0; i < sortedPair.Count; i++)
45 | {
46 | //TO-DO:Implement an algorithm factory and decouple it from here.
47 | if (algorithm == WeightAlgorithm.FairBiased)
48 | {
49 |
50 | randomValue -= sortedPair[i].Value;
51 | if (randomValue <= 0)
52 | return sortedPair[i].Key;
53 | }
54 | else
55 | {
56 | if (randomValue < sortedPair[i].Value)
57 | return sortedPair[i].Key;
58 |
59 | randomValue -= sortedPair[i].Value;
60 | }
61 |
62 | }
63 | return default; //Replace with random pick;
64 | }
65 |
66 | }
67 | }
68 |
--------------------------------------------------------------------------------