Skip to content

Commit 06ea7f9

Browse files
author
Cory Leach
committed
Noise Random Number Generator Implementation
1 parent 0028928 commit 06ea7f9

9 files changed

+370
-11
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace Gameframe.Procgen
2+
{
3+
/// <summary>
4+
/// Random number generator that provides random access to any position in its random number sequence
5+
/// </summary>
6+
public interface IRandomAccessRandomNumberGenerator : IRandomNumberGenerator
7+
{
8+
int Position { get; set; }
9+
}
10+
}

Runtime/Utility/IRandomAccessRandomNumberGenerator.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using UnityEngine;
2+
3+
namespace Gameframe.Procgen
4+
{
5+
/// <summary>
6+
/// Random number generator that provides lots of different convenience methods relevant for game development
7+
/// </summary>
8+
public interface IRandomNumberGenerator
9+
{
10+
uint Seed { get; }
11+
uint NextUint();
12+
ushort NextUshort();
13+
byte NextByte();
14+
int NextInt();
15+
short NextShort();
16+
float NextFloatZeroToOne();
17+
float NextFloatNegOneToOne();
18+
float NextFloatRange(float min, float max);
19+
bool RollChance(float probabilityOfReturningTrue);
20+
Vector2 NextDirection2D();
21+
Vector3 NextDirection3D();
22+
}
23+
}

Runtime/Utility/IRandomNumberGenerator.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/Utility/NoiseRng.cs

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
using System;
2+
using UnityEngine;
3+
4+
namespace Gameframe.Procgen
5+
{
6+
/// <summary>
7+
/// Noise based random number generator
8+
/// Allows for fast random-access within a sequence of generated numbers
9+
/// Based on GDC 2017 talk and code by Squirrel Eiserloh
10+
/// </summary>
11+
public class NoiseRng : IRandomAccessRandomNumberGenerator
12+
{
13+
private uint seed;
14+
private int position;
15+
16+
/// <summary>
17+
/// Initialize random number generator with a given seed
18+
/// </summary>
19+
/// <param name="seed">see for the random number generator</param>
20+
public NoiseRng(uint seed)
21+
{
22+
this.seed = seed;
23+
position = 0;
24+
}
25+
26+
/// <summary>
27+
/// Seeds using DateTime.UtcNow.Ticks
28+
/// </summary>
29+
public NoiseRng()
30+
{
31+
this.seed = (uint)DateTime.UtcNow.Ticks;
32+
position = 0;
33+
}
34+
35+
/// <summary>
36+
/// Current position in the number generator sequence
37+
/// </summary>
38+
public int Position
39+
{
40+
get => position;
41+
set => position = value;
42+
}
43+
44+
/// <summary>
45+
/// Current Seed
46+
/// </summary>
47+
public uint Seed => seed;
48+
49+
/// <summary>
50+
/// Reseed the number generator with a new seed and position
51+
/// </summary>
52+
/// <param name="seed">seed</param>
53+
/// <param name="position">position in number generation sequence</param>
54+
public void ReSeed(uint seed, int position = 0)
55+
{
56+
this.seed = seed;
57+
this.position = position;
58+
}
59+
60+
#region Rand Methods
61+
62+
/// <summary>
63+
/// Next random unsigned integer
64+
/// </summary>
65+
/// <returns>next random unsigned integer in the current sequence</returns>
66+
public uint NextUint()
67+
{
68+
return SquirrelEiserloh.Get1dNoiseUint(position++, seed);
69+
}
70+
71+
/// <summary>
72+
/// Next random unsigned short
73+
/// </summary>
74+
/// <returns>next random unsigned short in the current sequence</returns>
75+
public ushort NextUshort()
76+
{
77+
return unchecked((ushort)NextUint());
78+
}
79+
80+
/// <summary>
81+
/// Next random byte
82+
/// </summary>
83+
/// <returns>next random byte in the current sequence</returns>
84+
public byte NextByte()
85+
{
86+
return unchecked((byte)NextUint());
87+
}
88+
89+
/// <summary>
90+
/// Next random integer
91+
/// </summary>
92+
/// <returns>next random integer in the current sequence</returns>
93+
public int NextInt()
94+
{
95+
return unchecked((int)NextUint());
96+
}
97+
98+
/// <summary>
99+
/// Next random short
100+
/// </summary>
101+
/// <returns>next random short in the current sequence</returns>
102+
public short NextShort()
103+
{
104+
return unchecked((short)NextUint());
105+
}
106+
107+
/// <summary>
108+
/// Next random float in the range 0 to 1
109+
/// </summary>
110+
/// <returns>Next random float in the range 0 to 1 (inclusive, inclusive)</returns>
111+
public float NextFloatZeroToOne()
112+
{
113+
return SquirrelEiserloh.Get1dNoiseZeroToOne(position++, seed);
114+
}
115+
116+
/// <summary>
117+
/// Next random float in the range -1 to 1
118+
/// </summary>
119+
/// <returns>Next random float in the range -1 to 1 (inclusive, inclusive)</returns>
120+
public float NextFloatNegOneToOne()
121+
{
122+
return SquirrelEiserloh.Get1dNoiseNegOneToOne(position++, seed);
123+
}
124+
125+
/// <summary>
126+
/// Next random float in the range min to max
127+
/// </summary>
128+
/// <param name="min">min return value</param>
129+
/// <param name="max">max return value</param>
130+
/// <returns>Next random float in the range min to max (inclusive, inclusive)</returns>
131+
public float NextFloatRange(float min, float max)
132+
{
133+
var v= SquirrelEiserloh.Get1dNoiseZeroToOne(position++, seed);
134+
return min + (max - min) * v;
135+
}
136+
137+
/// <summary>
138+
/// Next random integer in the range min to max
139+
/// </summary>
140+
/// <param name="min">min return value</param>
141+
/// <param name="max">max return value</param>
142+
/// <returns>Next random int in the range min to max (inclusive, inclusive)</returns>
143+
public int NextIntRange(int min, int max)
144+
{
145+
return min + (int)((1 + max - min) * NextFloatZeroToOne());
146+
}
147+
148+
/// <summary>
149+
/// Rolls for a true for false with the given probability
150+
/// </summary>
151+
/// <param name="probabilityOfReturningTrue">probably that this function will return true</param>
152+
/// <returns>true or false</returns>
153+
public bool RollChance(float probabilityOfReturningTrue)
154+
{
155+
var v= SquirrelEiserloh.Get1dNoiseZeroToOne(position++, seed);
156+
return v < probabilityOfReturningTrue;
157+
}
158+
159+
/// <summary>
160+
/// Next uniformly distributed randomized 2d direction
161+
/// </summary>
162+
/// <returns>Random Normalized Vector2</returns>
163+
public Vector2 NextDirection2D()
164+
{
165+
var theta = NextFloatRange(0, 2*Mathf.PI);
166+
var v = new Vector2
167+
{
168+
x = Mathf.Cos(theta),
169+
y = Mathf.Sin(theta)
170+
};
171+
return v;
172+
}
173+
174+
/// <summary>
175+
/// Next uniformly distributed randomized 3d direction
176+
/// </summary>
177+
/// <returns>Random Normalized Vector3</returns>
178+
public Vector3 NextDirection3D()
179+
{
180+
//Random Polar coordinates with uniform distribution
181+
var phi = NextFloatRange(0, 2*Mathf.PI);
182+
var theta = Mathf.Acos(NextFloatNegOneToOne());
183+
184+
var v = new Vector3
185+
{
186+
x = Mathf.Cos(phi) * Mathf.Sin(theta),
187+
y = Mathf.Sin(phi) * Mathf.Sin(theta),
188+
z = Mathf.Cos(theta)
189+
};
190+
191+
return v;
192+
}
193+
194+
#endregion
195+
196+
}
197+
}

Runtime/Utility/NoiseRng.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using UnityEngine;
5+
using UnityEngine.Serialization;
6+
7+
namespace Gameframe.Procgen
8+
{
9+
public class RandomDirectionVisualizer : MonoBehaviour
10+
{
11+
public DirectionDimensions dimensions = DirectionDimensions.Dir3D;
12+
13+
public uint seed = 0;
14+
15+
public int pointCount = 200;
16+
17+
public float sphereRadius = 10;
18+
public float pointRadius = 0.1f;
19+
20+
public Color sphereColor = Color.white;
21+
public Color pointColor = Color.white;
22+
23+
private NoiseRng rand;
24+
25+
public enum DirectionDimensions
26+
{
27+
Dir2D,
28+
Dir3D,
29+
};
30+
31+
private void OnDrawGizmos()
32+
{
33+
if (rand == null)
34+
{
35+
rand = new NoiseRng(seed);
36+
}
37+
38+
rand.ReSeed(seed, 0);
39+
40+
Gizmos.color = sphereColor;
41+
Gizmos.DrawSphere(transform.position, sphereRadius);
42+
43+
Gizmos.color = pointColor;
44+
for (int i = 0; i < pointCount; i++)
45+
{
46+
var dir = dimensions == DirectionDimensions.Dir3D ? rand.NextDirection3D() : (Vector3)rand.NextDirection2D();
47+
Gizmos.DrawSphere(transform.position + dir * sphereRadius, pointRadius);
48+
}
49+
}
50+
}
51+
}

Runtime/Visualizers/RandomDirectionVisualizer.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)