Skip to content

Commit

Permalink
Added jump sound to surface audio resource.
Browse files Browse the repository at this point in the history
Modified all surface audio resources to be optional.
Fixed resource leak by not attempting to play null sounds.
Added signal emitted when a surface sound is played (possibly to alert enemies)
Made walk speed configurable.
Moved audio settings to an AudioStreamPlayer3D child node.
Modified when footsteps are played to be at the "end" of a step.
Modified all footstep sounds to be wave files to avoid delay when playing the sounds.
  • Loading branch information
Malcolmnixon committed Feb 25, 2023
1 parent ee47cd2 commit aa6fad3
Show file tree
Hide file tree
Showing 25 changed files with 201 additions and 159 deletions.
15 changes: 5 additions & 10 deletions addons/godot-xr-tools/audio/surface_audio_type.gd
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ extends Resource
## Surface name
export var name : String = ""

## Audio stream to play when the player lands on this surface
## Optional audio stream to play when the player jumps on this surface
export var jump_sound : AudioStream

## Optional audio stream to play when the player lands on this surface
export var hit_sound : AudioStream

## Audio streams to play when the player walks on this surface
Expand All @@ -27,17 +30,9 @@ export(float, 1.0, 2.0) var walk_pitch_maximum : float = 1.2

# This method checks for configuration issues.
func _get_configuration_warning():
# Verify the camera
# Verify the name
if name == "":
return "Surface audio type must have a name"

# Verify hit sound
if !hit_sound:
return "Surface audio type must specify a hit audio stream"

# Verify walk sounds
if walk_sounds.size() == 0:
return "Surface audio type must specify one or more walk audio streams"

# No configuration issues detected
return ""
132 changes: 68 additions & 64 deletions addons/godot-xr-tools/functions/movement_footstep.gd
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ extends XRToolsMovementProvider
## currently walking on.


# Some value indicating the player wants to walk at a moderate speed
const WALK_SOUND_THRESHOLD := 0.3
## Signal emitted when a footstep is generated
signal footstep(name)


# Number of audio players to pool
const AUDIO_POOL_SIZE := 3
Expand All @@ -20,25 +21,16 @@ const AUDIO_POOL_SIZE := 3
## Movement provider order
export var order : int = 1001

## Audio dB
export(float, -80.0, 80.0) var audio_db : float = 0.0

## Audio dB
export(float, -24.0, 6.0) var audio_max_db : float = 3.0

## Audio size
export(float, 0.1, 100.0) var audio_size : float = 3.0

## Audio max distance
export(float, 0.0, 4096.0) var audio_distance : float = 10.0

## Default XRToolsSurfaceAudioType when not overridden
export var default_surface_audio_type : Resource

## Speed at which the player is considered walking
export var walk_speed := 0.4

## Step per meter by time
export var steps_per_meter = 1.0


# step time
var step_time = 0.0

Expand Down Expand Up @@ -73,18 +65,13 @@ func _ready():
_foot_spatial.name = "FootSpatial"
add_child(_foot_spatial)

# Construct the pool of audio players
# Make the array of players in _audio_pool_idle
for i in AUDIO_POOL_SIZE:
var player := AudioStreamPlayer3D.new()
player.name = "AudioPlayer%d" % (i + 1)
player.attenuation_model = AudioStreamPlayer3D.ATTENUATION_INVERSE_SQUARE_DISTANCE
player.unit_db = audio_db
player.unit_size = audio_size
player.max_db = audio_max_db
player.max_distance = audio_distance
player.connect("finished", self, "_on_player_finished", [ player ])
var player = $PlayerSettings.duplicate()
player.name = "PlayerCopy%d" % (i + 1)
_foot_spatial.add_child(player)
_audio_pool_idle.append(player)
player.connect("finished", self, "_on_player_finished", [ player ])

# Set as always active
is_active = true
Expand All @@ -95,6 +82,10 @@ func _ready():

# This method checks for configuration issues.
func _get_configuration_warning():
# Verify player settings node exists
if !$PlayerSettings:
return "Missing player settings node"

# Verify hit sound
if default_surface_audio_type and !default_surface_audio_type is XRToolsSurfaceAudioType:
return "Default surface audio type is not an XRToolsSurfaceAudioType"
Expand All @@ -110,6 +101,11 @@ func physics_movement(_delta: float, player_body: XRToolsPlayerBody, _disabled:
# Update the ground audio information
_update_ground_audio()

# Skip if footsteps have been disabled
if not enabled:
step_time = 0
return

# Detect landing on ground
if not _old_on_ground and player_body.on_ground:
# Play the ground hit sound
Expand All @@ -118,25 +114,19 @@ func physics_movement(_delta: float, player_body: XRToolsPlayerBody, _disabled:
# Update the old on_ground state
_old_on_ground = player_body.on_ground
if not player_body.on_ground:
step_time = 0
step_time = 0 # Reset when not on ground
return

# Count down the step timer, and skip if silenced
step_time = max(0, step_time - _delta * player_body.ground_control_velocity.length())
if step_time > 0:
# Handle slow/stopped
if player_body.ground_control_velocity.length() < walk_speed:
step_time = 0 # Reset when slow/stopped
return

# Play walking sounds if the player is trying to walk
if player_body.ground_control_velocity.length() > WALK_SOUND_THRESHOLD:
# Play the step sound and set the step delay timer
# Count up the step timer, and skip if not take a step yet
step_time += _delta * player_body.ground_control_velocity.length()
if step_time > steps_per_meter:
_play_step_sound()
step_time = steps_per_meter


# Called when the player jumps
func _on_player_jumped() -> void:
# Play the hit sound for whatever ground the player was standing on
_play_ground_hit()
step_time = 0


# Update ther foot spatial to be where the players foot is
Expand Down Expand Up @@ -171,32 +161,34 @@ func _update_ground_audio() -> void:
_ground_node_audio_type = default_surface_audio_type


# Play the hit sound made when the player lands on the ground
func _play_ground_hit() -> void:
# Skip if no ground audio
# Called when the player jumps
func _on_player_jumped() -> void:
# Skip if no jump sound
if not _ground_node_audio_type:
return

# Get an idle audio player
var player := _get_idle_audio_player()
if not player:
# Play the jump sound
_play_sound(
_ground_node_audio_type.name,
_ground_node_audio_type.jump_sound)


# Play the hit sound made when the player lands on the ground
func _play_ground_hit() -> void:
# Skip if no hit sound
if not _ground_node_audio_type:
return

# Play the hit sound
player.stream = _ground_node_audio_type.hit_sound
player.pitch_scale = 1.0
player.play()
_play_sound(
_ground_node_audio_type.name,
_ground_node_audio_type.hit_sound)


# Play a step sound for the current ground
func _play_step_sound() -> void:
# Skip if no ground audio
if not _ground_node_audio_type:
return

# Get an idle audio player
var player := _get_idle_audio_player()
if not player:
# Skip if no walk audio
if not _ground_node_audio_type or _ground_node_audio_type.walk_sounds.size() == 0:
return

# Pick the sound index
Expand All @@ -208,20 +200,32 @@ func _play_step_sound() -> void:
_ground_node_audio_type.walk_pitch_maximum)

# Play the walk sound
player.stream = _ground_node_audio_type.walk_sounds[idx]
player.pitch_scale = pitch
player.play()
_play_sound(
_ground_node_audio_type.name,
_ground_node_audio_type.walk_sounds[idx],
pitch)


# Called to get an idle AudioStreamPlayer3D to play a sound
func _get_idle_audio_player() -> AudioStreamPlayer3D:
# Return the next idle player
if _audio_pool_idle.size() > 0:
return _audio_pool_idle.pop_front()
# Play the specified audio stream at the requested pitch using an
# AudioStreamPlayer3D in the idle pool of players.
func _play_sound(name : String, stream : AudioStream, pitch : float = 1.0) -> void:
# Skip if no stream provided
if not stream:
return

# Emit the footstep signal
emit_signal("footstep", name)

# No players available
push_warning("XRToolsMovementFootstep idle audio pool empty")
return null
# Verify we have an audio player
if _audio_pool_idle.size() == 0:
push_warning("XRToolsMovementFootstep idle audio pool empty")
return

# Play the sound
var player : AudioStreamPlayer3D = _audio_pool_idle.pop_front()
player.stream = stream
player.pitch_scale = pitch
player.play()


# Called when an AudioStreamPlayer3D in our pool finishes playing its sound
Expand Down
5 changes: 2 additions & 3 deletions addons/godot-xr-tools/functions/movement_footstep.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@

[node name="MovementFootstep" type="Node" groups=["movement_providers"]]
script = ExtResource( 1 )
audio_path = ""
crouch_path = ""
ground_only = true

[node name="PlayerSettings" type="AudioStreamPlayer3D" parent="."]
Binary file removed assets/footsteps/default_footstep.ogg
Binary file not shown.
15 changes: 0 additions & 15 deletions assets/footsteps/default_footstep.ogg.import

This file was deleted.

Binary file added assets/footsteps/default_footstep.wav
Binary file not shown.
23 changes: 23 additions & 0 deletions assets/footsteps/default_footstep.wav.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[remap]

importer="wav"
type="AudioStreamSample"
path="res://.import/default_footstep.wav-dd12f9efdea3173225647961887739e0.sample"

[deps]

source_file="res://assets/footsteps/default_footstep.wav"
dest_files=[ "res://.import/default_footstep.wav-dd12f9efdea3173225647961887739e0.sample" ]

[params]

force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=0
Binary file removed assets/footsteps/grass_footstep.ogg
Binary file not shown.
15 changes: 0 additions & 15 deletions assets/footsteps/grass_footstep.ogg.import

This file was deleted.

Binary file added assets/footsteps/grass_footstep.wav
Binary file not shown.
23 changes: 23 additions & 0 deletions assets/footsteps/grass_footstep.wav.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[remap]

importer="wav"
type="AudioStreamSample"
path="res://.import/grass_footstep.wav-b9825665a4e1ac3aee5f9998be56cb59.sample"

[deps]

source_file="res://assets/footsteps/grass_footstep.wav"
dest_files=[ "res://.import/grass_footstep.wav-b9825665a4e1ac3aee5f9998be56cb59.sample" ]

[params]

force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=0
Binary file removed assets/footsteps/mud_footstep.ogg
Binary file not shown.
15 changes: 0 additions & 15 deletions assets/footsteps/mud_footstep.ogg.import

This file was deleted.

Binary file added assets/footsteps/mud_footstep.wav
Binary file not shown.
23 changes: 23 additions & 0 deletions assets/footsteps/mud_footstep.wav.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[remap]

importer="wav"
type="AudioStreamSample"
path="res://.import/mud_footstep.wav-efdbb54cdc8800b21fa00335ae339ccc.sample"

[deps]

source_file="res://assets/footsteps/mud_footstep.wav"
dest_files=[ "res://.import/mud_footstep.wav-efdbb54cdc8800b21fa00335ae339ccc.sample" ]

[params]

force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=0
Binary file removed assets/footsteps/puddle_footstep.ogg
Binary file not shown.
15 changes: 0 additions & 15 deletions assets/footsteps/puddle_footstep.ogg.import

This file was deleted.

Binary file added assets/footsteps/puddle_footstep.wav
Binary file not shown.
Loading

0 comments on commit aa6fad3

Please sign in to comment.