Volume_Slider acting buggy, working after clicking Play and going back

Godot Version

Godot_v4.3-stable_mono_win64

Question

So basically, I am coding a game where you can play ultimate tic tac toe and simple tic tac toe, but whenever I start the game, the music I added works, but when I turn it down, its barely noticable, but when I click the PlayButton, and go back to home, the music works fine and I can turn it down and mute it, any ideas?

Here is a video to show what it’s doing

Here is the SceneTree for UI.tscn


VibesPlayer is my music player thingy

Here is some of my code to help

UI.gd (The script that contains the home screen)

extends Control

var credits_popup: Popup = null
var settings_popup: Popup = null
var button_click_player: AudioStreamPlayer = null  # Reference to the AudioStreamPlayer

#function ready
func _ready():
	# Initialize AudioStreamPlayer reference and set the sound stream
	button_click_player = $ButtonClickPlayer
	button_click_player.stream = load("res://sounds/click.ogg")

	if $SubscribeLabel:
		$SubscribeLabel.connect("gui_input", Callable(self, "_on_SubscribeLabel_clicked"))

	if $DiscordLabel:
		$DiscordLabel.connect("gui_input", Callable(self, "_on_DiscordLabel_clicked"))


# Function to play button click sound
func _play_button_click_sound():
	button_click_player.play()  # Play the button click sound

func _on_Button_pressed():
	_play_button_click_sound()  # Play the button click sound
	print("Credits Button Clicked!")  # Log button click to the console
	if credits_popup == null:  # Check if the popup is not created
		credits_popup = Popup.new()  # Create a new popup

		# Create a RichTextLabel for credits with clickable links
		var rich_text_label = RichTextLabel.new()  
		rich_text_label.bbcode_enabled = true  # Enable BBCode for clickable links
		rich_text_label.text = "Game by [url=yt link]MonkaGaming420YT[/url]/Anthony\n" + \
			"Song name at home page: [url=https://www.youtube.com/watch?v=x-ObUKegl6g]Vibes - David Renda[/url]\n" + \
			"Click sound effect: [url=https://freesound.org/people/Breviceps/sounds/448081]Tic Toc UI Click[/url]\n" + \
			"Simple Tic Tac Toe picture credits: [url=https://projectbook.code.brettchalupa.com/games/img/ttt.webp]https://projectbook.code.brettchalupa.com/games/img/ttt.webp[/url]\n" + \
			"Super Tic Tac Toe credits: [url=https://upload.wikimedia.org/wikipedia/commons/7/7d/Super_tic-tac-toe_rules_example.png]https://upload.wikimedia.org/wikipedia/commons/7/7d/Super_tic-tac-toe_rules_example.png[/url]\n"  # BBCode for clickable links

		# Set minimum size for the label
		rich_text_label.custom_minimum_size = Vector2(200, 100)  
		credits_popup.add_child(rich_text_label)  # Add the label to the popup
		
		# Connect the link click event to open the URL
		rich_text_label.connect("meta_clicked", Callable(self, "_on_link_clicked"))

		# Connect the close functionality
		credits_popup.connect("popup_hide", Callable(self, "_on_CreditsPopup_closed"))

		# Add the popup to the current scene
		get_tree().current_scene.add_child(credits_popup)  # Adding to the current scene

		# Position the popup in the center of the screen after it's been added to the tree
		credits_popup.popup_centered()  # Show it centered on the screen
	else:
		# If popup is already created, just show or hide it
		if credits_popup.is_visible():
			credits_popup.hide()  # Hide the popup if it's visible
		else:
			credits_popup.popup_centered()  # Show it centered on the screen

# Function to handle link clicks
func _on_link_clicked(meta: String):
	print("Clicked link: ", meta)  # Print the clicked link
	OS.shell_open(meta)  # Open the link in the default browser

func _on_PlayButton_pressed():
	print("Play Button sound trigger")
	_play_button_click_sound()  # Play the button click sound

	# Add a slight delay if necessary
	await get_tree().create_timer(0.15).timeout

	print("Play Button Pressed")
	get_tree().change_scene_to_file("res://ultimate_or_simple.tscn")

func _on_SettingsButton_pressed():
	_play_button_click_sound()  # Play the button click sound
	print("Settings Button Clicked!")  # Log button click to the console
	
	# Load and instance the SettingsPopup.tscn
	if settings_popup == null:  # Check if the popup is not created
		var packed_scene = preload("res://settingspopup.tscn")  # Preload the scene
		settings_popup = packed_scene.instantiate()  # Instantiate the scene
		get_tree().current_scene.add_child(settings_popup)  # Add to the current scene
		settings_popup.popup_centered()  # Show it centered on the screen
	else:
		if settings_popup.is_visible():
			settings_popup.hide()  # Hide the popup if it's visible
		else:
			settings_popup.popup_centered()  # Show it centered on the screen

func _on_SaveButton_pressed():
	_play_button_click_sound()  # Play the button click sound for the save button

	# Save settings logic can be modified here if you still want to save other settings
	print("Settings Saved.")


func _on_DiscordLabel_clicked(event: InputEvent):
	if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
		print("Discord Label Clicked!")  # Print message when Discord label is clicked
		OS.shell_open("my dsc link")  # Open Discord in default browser

# Function to handle when the SubscribeLabel is clicked
func _on_SubscribeLabel_clicked(event: InputEvent):
	if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
		print("Subscribe Label Clicked!")  # Print message when Subscribe label is clicked
		OS.shell_open("my yt link")  # Open YouTube channel in the default browser


func _on_SFXMuteButton_toggled(pressed: bool):
	# Mute or unmute the SFX based on the button state
	if pressed:
		print("SFX Muted")
		AudioServer.set_bus_volume_db(AudioServer.get_bus_index("SFX"), -60)  # Mute SFX
	else:
		print("SFX Unmuted")
		AudioServer.set_bus_volume_db(AudioServer.get_bus_index("SFX"), 0)  # Unmute SFX

Here is settingspopup.gd (the script that contains the settings pop up and somewhat controls the music across the whole game)

extends Popup

# Member variables for controls
var volume_slider: HSlider
var sfx_mute: CheckButton
var save_button: Button
var close_button: Button
var color_rect: ColorRect
var vbox_container: VBoxContainer
var vibes_player: VibesPlayer  # Changed to specific type for better clarity

# Called when the node enters the scene tree for the first time.
func _ready():
	vbox_container = get_node("VBoxContainer")
	volume_slider = vbox_container.get_node("Volume_Slider")
	sfx_mute = vbox_container.get_node("SFXMute")
	save_button = vbox_container.get_node("Save_Button")
	close_button = vbox_container.get_node("Close_Button")
	color_rect = get_node("ColorRect")

	color_rect.show()
	color_rect.color = Color(0.3, 0.3, 0.3, 1)  # Set to a darker gray

	# Set the size of the ColorRect
	color_rect.size = Vector2(100, 150)  # Adjust the size as needed

	# Set the size of the popup
	size = Vector2(300, 150)  # Adjusted for better visibility

	# Show the popup
	popup()

	# Adjust size flags
	vbox_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL
	vbox_container.size_flags_vertical = Control.SIZE_EXPAND_FILL

	# Get reference to VibesPlayer from the current scene or UI
	vibes_player = get_tree().current_scene.get_node("VibesPlayer")  # Adjust path as needed
	if not vibes_player:
		print("VibesPlayer not found in the current scene")

	# Initialize slider and mute state
	initialize_controls()

	# Call the method to connect signals
	_connect_signals()

# Function to initialize controls based on the current state of VibesPlayer
func initialize_controls():
	if vibes_player:
		volume_slider.value = (vibes_player.volume_db + 60) / 60 * 100  # Correctly map the volume
		sfx_mute.set_pressed(volume_slider.value == 0)  # Mute if volume is 0
	else:
		print("No valid VibesPlayer found.")

# Function to connect signals
func _connect_signals():
	# Disconnect previous connections to avoid multiple connections
	if volume_slider.is_connected("value_changed", Callable(self, "_on_Volume_Slider_value_changed")):
		volume_slider.disconnect("value_changed", Callable(self, "_on_Volume_Slider_value_changed"))
	volume_slider.connect("value_changed", Callable(self, "_on_Volume_Slider_value_changed"))

	if sfx_mute.is_connected("toggled", Callable(self, "_on_SFXMute_toggled")):
		sfx_mute.disconnect("toggled", Callable(self, "_on_SFXMute_toggled"))
	sfx_mute.connect("toggled", Callable(self, "_on_SFXMute_toggled"))

# Function to handle volume slider value change
func _on_Volume_Slider_value_changed(value: float):
	if vibes_player:
		print("Volume slider changed to:", value)  # Debugging
		# Convert slider value to dB and adjust the volume of VibesPlayer
		var volume_db = value_to_db(value)
		vibes_player.set_volume_db(volume_db)  # Use the set_volume_db function in VibesPlayer

# Function to handle SFX mute button state change
func _on_SFXMute_toggled(pressed: bool):
	if vibes_player:  # Use the member variable instead of redeclaring it
		if pressed:
			vibes_player.set_volume_db(-80)  # Mute
			volume_slider.value = 0  # Update slider position
		else:
			vibes_player.set_volume_db((volume_slider.value / 100.0) * 60 - 60)  # Restore volume

# Function to convert slider value to dB
func value_to_db(value: float) -> float:
	return (value / 100.0) * 60 - 60  # Scale from 0 to -60 dB

# Function to handle save button pressed
func _on_SaveButton_pressed():
	# Add your save logic here
	print("Save button pressed")
	var volume_value = volume_slider.value
	var is_muted = sfx_mute.is_pressed()
	print("Volume:", volume_value)
	print("SFX Mute:", is_muted)

# Function to handle close button pressed
func _on_CloseButton_pressed():
	hide()  # Hide the popup when closed
	print("Popup closed")

Here is VibesPlayer.gd (the script for the music)

extends AudioStreamPlayer

class_name VibesPlayer

func _ready():
	# Set the initial volume
	set_volume(100.0)  # Set initial volume to maximum (or any desired value)
	
	# Delay starting playback to ensure everything is ready
	await get_tree().create_timer(0.1).timeout  # Wait for 0.1 seconds
	play()  # Start playing the audio

	# Connect the 'finished' signal to handle when the audio finishes playing
	self.connect("finished", Callable(self, "_on_finished"))

func set_volume(value: float):
	volume_db = value_to_db(value)

func value_to_db(value: float) -> float:
	return (value / 100.0) * 60 - 60  # Convert slider value to dB

# Signal handler for when the audio finishes
func _on_finished():
	# Play the audio again at normal speed
	play()  # Play the audio again

Here is MusicPlayer.gd (The script that controls the music but is connected to the singleton in my project settings)

extends Node

# Preload the VibesPlayer script to ensure it's recognized
var VibesPlayerScript = preload("res://VibesPlayer.gd")  # Ensure the path is correct

var vibes_player: VibesPlayer  # Now it recognizes the class name

func _ready():
	vibes_player = VibesPlayerScript.new()  # Instantiate the VibesPlayer class

	# Add the vibes_player to the current scene instead of the root
	get_tree().current_scene.add_child(vibes_player)  # Add to the current scene

	vibes_player.stream = load("res://vibes.ogg")  # Ensure this path is correct

	# Call play deferred to ensure the node is inside the tree
	vibes_player.call_deferred("play")

Let me know if you need any extra scripts or SceneTree’s to help with this, Thank you so much :slight_smile:

Maybe you mean to use the built-in functiln linear_to_db as your current equation does not convert to decibels. linear_to_db accepts ranges from 0.0 to 1.0, so adjust your slider to that range instead of over 0 to 100

1 Like

sorry for the non-instant response, but yes that did work, and now it turns down properly and music plays properly

func value_to_db(value: float) -> float:
	var linear_value = value / 100.0  # Scale from 0 to 100 to 0 to 1
	if linear_value > 0:
		return linear_to_db(linear_value)  # Convert to dB using the built-in function
	else:
		return -80.0  # Return a low dB value for 0 volume (mute)

After exprimenting with that i got it to work
Thank you so much! :slight_smile:

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.