Repetitive sounds are very noticeable to humans. In games, we’re always trying to vary effects, so they don’t sound too similar.
We have two tools for that:
This is such a common pattern in almost every game that we decided to make it into a custom node.
Additionally, this allows us to demonstrate how easy it is to build your own nodes with custom functionality.
In the props/
directory, create a new script. Call it
RandomAudioPlayer2D
.
At the top, write:
class_name RandomAudioPlayer2D
extends AudioStreamPlayer2D
We’re going to export two variables.
The first, sounds
, will be an array of audio files. We
will pick a random file from it.
Not every RandomAudioPlayer2D
needs to have a list of
sounds. Sometimes, one sound is enough, and we just change the
pitch.
So if no sounds are provided in the sounds
array, we
want the player to behave normally.
export(Array, AudioStream) var sounds = []
The second variable, randomize_pitch
, will be a boolean.
If it is True
, we will shift the pitch randomly before
playing.
export var randomize_pitch := true
We only have one function to write. We want to override the default
play()
function of the
AudioStreamPlayer2D
.
If we look up the definition of this function in the documentation, we get:
We need to implement the exact same function signature. A function signature is the summary of the inputs it takes and what it returns.
In this instance, play()
receives a float
,
and returns void
. We need to write it exactly like that so
we can override it. Otherwise, we will get an error.
func play(from_position = 0.0) -> void:
pass
The function we need to write needs to do the following:
stream
property.randomize_pitch
is true:
pitch_scale
property to a random number between
0.9
and 1.6
(we can pick other numbers. You
can test different values and see how that works out).play()
so
we can play the sound with those new properties we set.Try to write it! If you’re stuck, the solution is below:
func play(from_position = 0.0) -> void:
if sounds:
= sounds[randi() % sounds.size()]
stream if randomize_pitch:
= rand_range(0.9, 1.6)
pitch_scale play(from_position) .
Once this class is created, we can use it anywhere we would use an
AudioStreamPlayer2D
.
For example, we will find it in the Create New Node dialog.
We can now add this node to the Robot, the mob, and use it there.
Open the robot scene. There are two AudioStreamPlayer2D
nodes there.
Locate the script you just wrote, and drag it over the first, then the second node
You’ll notice the script gets attached.
You’ll also find the script referenced in the Inspector at the very bottom:
More importantly, the sounds
and
randomize_pitch
variables will show up in the
Inspector.
Press the first pain_01.wav
file once. Then press
Shift, and press the last pain_05.wav
.
drag the files over the sounds
array of the
DamageAudio node:
That’s how you use this node!
Do the same with the DeathAudio node and the
death_xx.wav
files.
While mobs, bullets, spells, and pickups don’t have alternate audio
files, they can still profit from the randomize_pitch
functionality, so make sure to add the script to all the
AudioStreamPlayer2D
nodes you encounter.
Note: For inherited scenes like
Mob.tscn
, Spell.tscn
, and so on, you only need
to attach the script in the base scene. All inherited scenes will be
able to use it too.