|
@@ -42,25 +42,54 @@ In global scope, you can find a :ref:`randomize()
|
|
|
once when your project starts to initialize the random seed.** Calling it
|
|
|
multiple times is unnecessary and may impact performance negatively.
|
|
|
|
|
|
-Putting it in your main scene script's ``_ready()`` method is a good choice::
|
|
|
+Putting it in your main scene script's ``_ready()`` method is a good choice:
|
|
|
+
|
|
|
+.. tabs::
|
|
|
+ .. code-tab:: gdscript GDScript
|
|
|
|
|
|
func _ready():
|
|
|
randomize()
|
|
|
|
|
|
+ .. code-tab:: csharp
|
|
|
+
|
|
|
+ public override void _Ready()
|
|
|
+ {
|
|
|
+ GD.Randomize();
|
|
|
+ }
|
|
|
+
|
|
|
You can also set a fixed random seed instead using :ref:`seed()
|
|
|
<class_@GDScript_method_seed>`. Doing so will give you *deterministic* results
|
|
|
-across runs::
|
|
|
+across runs:
|
|
|
+
|
|
|
+.. tabs::
|
|
|
+ .. code-tab:: gdscript GDScript
|
|
|
|
|
|
func _ready():
|
|
|
seed(12345)
|
|
|
# To use a string as a seed, you can hash it to a number.
|
|
|
seed("Hello world".hash())
|
|
|
|
|
|
+ .. code-tab:: csharp
|
|
|
+
|
|
|
+ public override void _Ready()
|
|
|
+ {
|
|
|
+ GD.Seed(12345);
|
|
|
+ GD.Seed("Hello world".Hash());
|
|
|
+ }
|
|
|
+
|
|
|
When using the RandomNumberGenerator class, you should call ``randomize()`` on
|
|
|
-the instance since it has its own seed::
|
|
|
+the instance since it has its own seed:
|
|
|
|
|
|
- var rng = RandomNumberGenerator.new()
|
|
|
- rng.randomize()
|
|
|
+.. tabs::
|
|
|
+ .. code-tab:: gdscript GDScript
|
|
|
+
|
|
|
+ var random = RandomNumberGenerator.new()
|
|
|
+ random.randomize()
|
|
|
+
|
|
|
+ .. code-tab:: csharp
|
|
|
+
|
|
|
+ var random = new RandomNumberGenerator();
|
|
|
+ random.Randomize();
|
|
|
|
|
|
Getting a random number
|
|
|
-----------------------
|
|
@@ -71,7 +100,10 @@ random numbers in Godot.
|
|
|
The function :ref:`randi() <class_@GDScript_method_randi>` returns a random
|
|
|
number between 0 and 2^32-1. Since the maximum value is huge, you most likely
|
|
|
want to use the modulo operator (``%``) to bound the result between 0 and the
|
|
|
-denominator::
|
|
|
+denominator:
|
|
|
+
|
|
|
+.. tabs::
|
|
|
+ .. code-tab:: gdscript GDScript
|
|
|
|
|
|
# Prints a random integer between 0 and 49.
|
|
|
print(randi() % 50)
|
|
@@ -79,6 +111,14 @@ denominator::
|
|
|
# Prints a random integer between 10 and 60.
|
|
|
print(randi() % 51 + 10)
|
|
|
|
|
|
+ .. code-tab:: csharp
|
|
|
+
|
|
|
+ // Prints a random integer between 0 and 49.
|
|
|
+ GD.Print(GD.Randi() % 50);
|
|
|
+
|
|
|
+ // Prints a random integer between 10 and 60.
|
|
|
+ GD.Print(GD.Randi() % 51 + 10);
|
|
|
+
|
|
|
:ref:`randf() <class_@GDScript_method_randf>` returns a random floating-point
|
|
|
number between 0 and 1. This is useful to implement a
|
|
|
:ref:`doc_random_number_generation_weighted_random_probability` system, among
|
|
@@ -87,83 +127,169 @@ other things.
|
|
|
:ref:`randfn() <class_RandomNumberGenerator_method_randfn>` returns a random
|
|
|
floating-point number following a `normal distribution
|
|
|
<https://en.wikipedia.org/wiki/Normal_distribution>`__. This means the returned
|
|
|
-value is more likely to be around the mean (0.0 by default), varying by the deviation (1.0 by default)::
|
|
|
+value is more likely to be around the mean (0.0 by default),
|
|
|
+varying by the deviation (1.0 by default):
|
|
|
+
|
|
|
+.. tabs::
|
|
|
+ .. code-tab:: gdscript GDScript
|
|
|
|
|
|
# Prints a random floating-point number from a normal distribution with a mean 0.0 and deviation 1.0.
|
|
|
- var rng = RandomNumberGenerator.new()
|
|
|
- rng.randomize()
|
|
|
- print(rng.randfn())
|
|
|
+ var random = RandomNumberGenerator.new()
|
|
|
+ random.randomize()
|
|
|
+ print(random.randfn())
|
|
|
+
|
|
|
+ .. code-tab:: csharp
|
|
|
+
|
|
|
+ // Prints a normally distributed floating-point number between 0.0 and 1.0.
|
|
|
+ var random = new RandomNumberGenerator();
|
|
|
+ random.Randomize();
|
|
|
+ GD.Print(random.Randfn());
|
|
|
|
|
|
:ref:`rand_range() <class_@GDScript_method_rand_range>` takes two arguments
|
|
|
``from`` and ``to``, and returns a random floating-point number between ``from``
|
|
|
-and ``to``::
|
|
|
+and ``to``:
|
|
|
+
|
|
|
+.. tabs::
|
|
|
+ .. code-tab:: gdscript GDScript
|
|
|
|
|
|
# Prints a random floating-point number between -4 and 6.5.
|
|
|
print(rand_range(-4, 6.5))
|
|
|
|
|
|
+ .. code-tab:: csharp
|
|
|
+
|
|
|
+ // Prints a random floating-point number between -4 and 6.5.
|
|
|
+ GD.Print(GD.RandRange(-4, 6.5));
|
|
|
+
|
|
|
:ref:`RandomNumberGenerator.randi_range()
|
|
|
<class_RandomNumberGenerator_method_randi_range>` takes two arguments ``from``
|
|
|
-and ``to``, and returns a random integer between ``from`` and ``to``::
|
|
|
+and ``to``, and returns a random integer between ``from`` and ``to``:
|
|
|
+
|
|
|
+.. tabs::
|
|
|
+ .. code-tab:: gdscript GDScript
|
|
|
|
|
|
# Prints a random integer between -10 and 10.
|
|
|
- var rng = RandomNumberGenerator.new()
|
|
|
- rng.randomize()
|
|
|
- print(rng.randi_range(-10, 10))
|
|
|
+ var random = RandomNumberGenerator.new()
|
|
|
+ random.randomize()
|
|
|
+ print(random.randi_range(-10, 10))
|
|
|
+
|
|
|
+ .. code-tab:: csharp
|
|
|
+
|
|
|
+ # Prints a random integer number between -10 and 10.
|
|
|
+ random.Randomize();
|
|
|
+ GD.Print(random.RandiRange(-10, 10));
|
|
|
|
|
|
Get a random array element
|
|
|
--------------------------
|
|
|
|
|
|
-We can use random integer generation to get a random element from an array::
|
|
|
+We can use random integer generation to get a random element from an array:
|
|
|
|
|
|
- var fruits = ["apple", "orange", "pear", "banana"]
|
|
|
+.. tabs::
|
|
|
+ .. code-tab:: gdscript GDScript
|
|
|
|
|
|
+ var _fruits = ["apple", "orange", "pear", "banana"]
|
|
|
|
|
|
func _ready():
|
|
|
randomize()
|
|
|
|
|
|
- for i in 100:
|
|
|
+ for i in range(100):
|
|
|
# Pick 100 fruits randomly.
|
|
|
- # (``for i in 100`` is a faster shorthand for ``for i in range(100)``.)
|
|
|
print(get_fruit())
|
|
|
|
|
|
|
|
|
func get_fruit():
|
|
|
- var random_fruit = fruits[randi() % fruits.size()]
|
|
|
+ var random_fruit = _fruits[randi() % _fruits.size()]
|
|
|
# Returns "apple", "orange", "pear", or "banana" every time the code runs.
|
|
|
# We may get the same fruit multiple times in a row.
|
|
|
return random_fruit
|
|
|
|
|
|
+ .. code-tab:: csharp
|
|
|
+
|
|
|
+ private string[] _fruits = { "apple", "orange", "pear", "banana" };
|
|
|
+
|
|
|
+ public override void _Ready()
|
|
|
+ {
|
|
|
+ GD.Randomize();
|
|
|
+
|
|
|
+ for (int i = 0; i < 100; i++)
|
|
|
+ {
|
|
|
+ // Pick 100 fruits randomly.
|
|
|
+ GD.Print(GetFruit());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public string GetFruit()
|
|
|
+ {
|
|
|
+ string randomFruit = _fruits[GD.Randi() % _fruits.Length];
|
|
|
+ // Returns "apple", "orange", "pear", or "banana" every time the code runs.
|
|
|
+ // We may get the same fruit multiple times in a row.
|
|
|
+ return randomFruit;
|
|
|
+ }
|
|
|
+
|
|
|
To prevent the same fruit from being picked more than once in a row, we can add
|
|
|
-more logic to this method::
|
|
|
+more logic to this method:
|
|
|
|
|
|
- var fruits = ["apple", "orange", "pear", "banana"]
|
|
|
- var last_fruit = ""
|
|
|
+.. tabs::
|
|
|
+ .. code-tab:: gdscript GDScript
|
|
|
+
|
|
|
+ var _fruits = ["apple", "orange", "pear", "banana"]
|
|
|
+ var _last_fruit = ""
|
|
|
|
|
|
|
|
|
func _ready():
|
|
|
randomize()
|
|
|
|
|
|
# Pick 100 fruits randomly.
|
|
|
- # Note: ``for i in 100`` is a shorthand for ``for i in range(100)``.
|
|
|
- for i in 100:
|
|
|
+ for i in range(100):
|
|
|
print(get_fruit())
|
|
|
|
|
|
|
|
|
func get_fruit():
|
|
|
- var random_fruit = fruits[randi() % fruits.size()]
|
|
|
- while random_fruit == last_fruit:
|
|
|
+ var random_fruit = _fruits[randi() % _fruits.size()]
|
|
|
+ while random_fruit == _last_fruit:
|
|
|
# The last fruit was picked, try again until we get a different fruit.
|
|
|
- random_fruit = fruits[randi() % fruits.size()]
|
|
|
+ random_fruit = _fruits[randi() % _fruits.size()]
|
|
|
|
|
|
# Note: if the random element to pick is passed by reference,
|
|
|
# such as an array or dictionary,
|
|
|
- # use `last_fruit = random_fruit.duplicate()` instead.
|
|
|
- last_fruit = random_fruit
|
|
|
+ # use `_last_fruit = random_fruit.duplicate()` instead.
|
|
|
+ _last_fruit = random_fruit
|
|
|
|
|
|
# Returns "apple", "orange", "pear", or "banana" every time the code runs.
|
|
|
# The function will never return the same fruit more than once in a row.
|
|
|
return random_fruit
|
|
|
|
|
|
+ .. code-tab:: csharp
|
|
|
+
|
|
|
+ private string[] _fruits = { "apple", "orange", "pear", "banana" };
|
|
|
+ private string _lastFruit = "";
|
|
|
+
|
|
|
+ public override void _Ready()
|
|
|
+ {
|
|
|
+ GD.Randomize();
|
|
|
+
|
|
|
+ for (int i = 0; i < 100; i++)
|
|
|
+ {
|
|
|
+ // Pick 100 fruits randomly.
|
|
|
+ GD.Print(GetFruit());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public string GetFruit()
|
|
|
+ {
|
|
|
+ string randomFruit = _fruits[GD.Randi() % _fruits.Length];
|
|
|
+ while (randomFruit == _lastFruit)
|
|
|
+ {
|
|
|
+ // The last fruit was picked, try again until we get a different fruit.
|
|
|
+ randomFruit = _fruits[GD.Randi() % _fruits.Length];
|
|
|
+ }
|
|
|
+
|
|
|
+ _lastFruit = randomFruit;
|
|
|
+
|
|
|
+ // Returns "apple", "orange", "pear", or "banana" every time the code runs.
|
|
|
+ // The function will never return the same fruit more than once in a row.
|
|
|
+ return randomFruit;
|
|
|
+ }
|
|
|
+
|
|
|
This approach can be useful to make random number generation feel less
|
|
|
repetitive. Still, it doesn't prevent results from "ping-ponging" between a
|
|
|
limited set of values. To prevent this, use the :ref:`shuffle bag
|
|
@@ -172,7 +298,10 @@ limited set of values. To prevent this, use the :ref:`shuffle bag
|
|
|
Get a random dictionary value
|
|
|
-----------------------------
|
|
|
|
|
|
-We can apply similar logic from arrays to dictionaries as well::
|
|
|
+We can apply similar logic from arrays to dictionaries as well:
|
|
|
+
|
|
|
+.. tabs::
|
|
|
+ .. code-tab:: gdscript GDScript
|
|
|
|
|
|
var metals = {
|
|
|
"copper": {"quantity": 50, "price": 50},
|
|
@@ -184,7 +313,7 @@ We can apply similar logic from arrays to dictionaries as well::
|
|
|
func _ready():
|
|
|
randomize()
|
|
|
|
|
|
- for i in 20:
|
|
|
+ for i in range(20):
|
|
|
print(get_metal())
|
|
|
|
|
|
|
|
@@ -194,7 +323,6 @@ We can apply similar logic from arrays to dictionaries as well::
|
|
|
# The same metal may be selected multiple times in succession.
|
|
|
return random_metal
|
|
|
|
|
|
-
|
|
|
.. _doc_random_number_generation_weighted_random_probability:
|
|
|
|
|
|
Weighted random probability
|
|
@@ -202,12 +330,15 @@ Weighted random probability
|
|
|
|
|
|
The :ref:`randf() <class_@GDScript_method_randf>` method returns a
|
|
|
floating-point number between 0.0 and 1.0. We can use this to create a
|
|
|
-"weighted" probability where different outcomes have different likelihoods::
|
|
|
+"weighted" probability where different outcomes have different likelihoods:
|
|
|
+
|
|
|
+.. tabs::
|
|
|
+ .. code-tab:: gdscript GDScript
|
|
|
|
|
|
func _ready():
|
|
|
randomize()
|
|
|
|
|
|
- for i in 100:
|
|
|
+ for i in range(100):
|
|
|
print(get_item_rarity())
|
|
|
|
|
|
|
|
@@ -224,6 +355,39 @@ floating-point number between 0.0 and 1.0. We can use this to create a
|
|
|
# 5% chance of being returned.
|
|
|
return "Rare"
|
|
|
|
|
|
+ .. code-tab:: csharp
|
|
|
+
|
|
|
+ public override void _Ready()
|
|
|
+ {
|
|
|
+ GD.Randomize();
|
|
|
+
|
|
|
+ for (int i = 0; i < 100; i++)
|
|
|
+ {
|
|
|
+ GD.Print(GetItemRarity());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public string GetItemRarity()
|
|
|
+ {
|
|
|
+ float randomFloat = GD.Randf();
|
|
|
+
|
|
|
+ if (randomFloat < 0.8f)
|
|
|
+ {
|
|
|
+ // 80% chance of being returned.
|
|
|
+ return "Common";
|
|
|
+ }
|
|
|
+ else if (randomFloat < 0.95f)
|
|
|
+ {
|
|
|
+ // 15% chance of being returned
|
|
|
+ return "Uncommon";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 5% chance of being returned.
|
|
|
+ return "Rare";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
.. _doc_random_number_generation_shuffle_bags:
|
|
|
|
|
|
"Better" randomness using shuffle bags
|
|
@@ -238,29 +402,29 @@ You can accomplish this using the *shuffle bag* pattern. It works by removing an
|
|
|
element from the array after choosing it. After multiple selections, the array
|
|
|
ends up empty. When that happens, you reinitialize it to its default value::
|
|
|
|
|
|
- var fruits = ["apple", "orange", "pear", "banana"]
|
|
|
+ var _fruits = ["apple", "orange", "pear", "banana"]
|
|
|
# A copy of the fruits array so we can restore the original value into `fruits`.
|
|
|
- var fruits_full = []
|
|
|
+ var _fruits_full = []
|
|
|
|
|
|
|
|
|
func _ready():
|
|
|
randomize()
|
|
|
- fruits_full = fruits.duplicate()
|
|
|
- fruits.shuffle()
|
|
|
+ _fruits_full = _fruits.duplicate()
|
|
|
+ _fruits.shuffle()
|
|
|
|
|
|
for i in 100:
|
|
|
print(get_fruit())
|
|
|
|
|
|
|
|
|
func get_fruit():
|
|
|
- if fruits.empty():
|
|
|
+ if _fruits.empty():
|
|
|
# Fill the fruits array again and shuffle it.
|
|
|
- fruits = fruits_full.duplicate()
|
|
|
- fruits.shuffle()
|
|
|
+ _fruits = _fruits_full.duplicate()
|
|
|
+ _fruits.shuffle()
|
|
|
|
|
|
# Get a random fruit, since we shuffled the array,
|
|
|
- # and remove it from the `fruits` array.
|
|
|
- var random_fruit = fruits.pop_front()
|
|
|
+ # and remove it from the `_fruits` array.
|
|
|
+ var random_fruit = _fruits.pop_front()
|
|
|
# Prints "apple", "orange", "pear", or "banana" every time the code runs.
|
|
|
return random_fruit
|
|
|
|
|
@@ -279,19 +443,41 @@ time, or anything else.
|
|
|
To achieve this, you can use random *noise* functions. Noise functions are
|
|
|
especially popular in procedural generation to generate realistic-looking
|
|
|
terrain. Godot provides :ref:`class_opensimplexnoise` for this, which supports
|
|
|
-1D, 2D, 3D, and 4D noise. Here's an example with 1D noise::
|
|
|
+1D, 2D, 3D, and 4D noise. Here's an example with 1D noise:
|
|
|
+
|
|
|
+.. tabs::
|
|
|
+ .. code-tab:: gdscript GDScript
|
|
|
|
|
|
- var noise = OpenSimplexNoise.new()
|
|
|
+ var _noise = OpenSimplexNoise.new()
|
|
|
|
|
|
func _ready():
|
|
|
randomize()
|
|
|
# Configure the OpenSimplexNoise instance.
|
|
|
- noise.seed = randi()
|
|
|
- noise.octaves = 4
|
|
|
- noise.period = 20.0
|
|
|
- noise.persistence = 0.8
|
|
|
+ _noise.seed = randi()
|
|
|
+ _noise.octaves = 4
|
|
|
+ _noise.period = 20.0
|
|
|
+ _noise.persistence = 0.8
|
|
|
|
|
|
for i in 100:
|
|
|
# Prints a slowly-changing series of floating-point numbers
|
|
|
# between -1.0 and 1.0.
|
|
|
- print(noise.get_noise_1d(i))
|
|
|
+ print(_noise.get_noise_1d(i))
|
|
|
+
|
|
|
+ .. code-tab:: csharp
|
|
|
+
|
|
|
+ private OpenSimplexNoise _noise = new OpenSimplexNoise();
|
|
|
+
|
|
|
+ public override void _Ready()
|
|
|
+ {
|
|
|
+ GD.Randomize();
|
|
|
+ // Configure the OpenSimplexNoise instance.
|
|
|
+ _noise.Seed = (int)GD.Randi();
|
|
|
+ _noise.Octaves = 4;
|
|
|
+ _noise.Period = 20.0f;
|
|
|
+ _noise.Persistence = 0.8f;
|
|
|
+
|
|
|
+ for (int i = 0; i < 100; i++)
|
|
|
+ {
|
|
|
+ GD.Print(_noise.GetNoise1d(i));
|
|
|
+ }
|
|
|
+ }
|