Saving settings inside the game, and loading at startup

Godot Version

Godot Engine 4.5

Question

Hello everyone. I can’t figure out how to save the settings to a file, with these settings loaded at the start of the game. Settings by type of screen resolution, full screen mode, and music volume.
I am attaching the script code:


extends Control

var settings = ConfigFile.new()
var resolution_index = 0
var current_display_mode = DisplayServer.WINDOW_MODE_FULLSCREEN
var music_volume_value = -25
var main_theme_index = 0

Called when the node enters the scene tree for the first time.

func _ready() → void:
resolution_index = settings.get_value(“Graphic”,“Resolution”)
current_display_mode = settings.get_value(“Graphic”,“Fullscreen”)
music_volume_value = settings.get_value(“Graphic”,“Resolution”)
get_node(“StartButton”).set_visible(1)
get_node(“MainMenuGroup”).set_visible(0)
pass # Replace with function body.

Called every frame. ‘delta’ is the elapsed time since the previous frame.

func _process(_delta: float) → void:
pass

#Блок с кнопкой “Играть”
func _on_play_pressed() → void:
get_tree().change_scene_to_file(“res://TSCN/start.tscn”)
pass # Replace with function body.

#Блок с кнопкой “Настройки”
func _on_settings_pressed() → void:
get_node(“MainMenuGroup”).set_visible(0)
get_node(“SettingsGroup”).set_visible(1)
pass # Replace with function body.

func _on_resolution_item_selected(resolution_index: int) → int:
match resolution_index:
0 :
DisplayServer.window_set_size(Vector2i(2560,1440))
1 :
DisplayServer.window_set_size(Vector2i(1920,1080))
2 :
DisplayServer.window_set_size(Vector2i(1280,720))
return resolution_index # Replace with function body.

func _on_fullscreen_toggled(current_display_mode: bool) → int:
if current_display_mode == false:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
print(“WINDOWED”)
elif current_display_mode == true:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
print(“FULLSCREEN”)
return current_display_mode

func _on_music_slider_value_changed(music_volume_value: int) → int:
get_node(“SettingsGroup/Sound/AudioStreamPlayer”).set_volume_db(music_volume_value)
if music_volume_value <= -40:
get_node(“SettingsGroup/Sound/AudioStreamPlayer”).set_stream_paused(true)
if music_volume_value > -40: get_node(“SettingsGroup/Sound/AudioStreamPlayer”).set_stream_paused(false)
return music_volume_value # Replace with function body.

func _on_main_theme_b_item_selected() → int:
print(“hello world”)
return main_theme_index # Replace with function body.

func _on_back_fs_pressed() → void:
# Сохраните некоторые значения.
settings.set_value(“Graphic”,“Fullscreen”,current_display_mode)
settings.set_value(“Graphic”,“Resolution”,resolution_index)
settings.set_value(“Sound”,“MusicVolume”,music_volume_value)
# Сохраните его в файле (перезапишите, если он уже существует).
settings.save(“res://SAVES/settings.cfg”)

get_node("SettingsGroup").set_visible(0)
get_node("MainMenuGroup").set_visible(1)
pass # Replace with function body.

#Блок с кнопкой “Об авторах”
func _on_about_pressed() → void:
get_node(“MainMenuGroup”).set_visible(0)
get_node(“AboutGroup”).set_visible(1)
pass # Replace with function body.

func _on_back_fa_pressed() → void:
get_node(“MainMenuGroup”).set_visible(1)
get_node(“AboutGroup”).set_visible(0)
pass # Replace with function body.

#Остальные кнопки

func _on_language_pressed() → void:

pass # Replace with function body.

func _on_exit_pressed() → void:
get_tree().quit()
pass # Replace with function body.

func _on_start_button_pressed() → void:
get_node(“StartButton”).set_visible(0)
get_node(“MainMenuGroup”).set_visible(1)
pass # Replace with function body.


(I’m sorry in advance for the stupid moments in the code, I’m just starting my way in programming)

the ConfigFile must also call .load to load from your save file, such as on ready.

You cannot save to “res://” in exported projects, so it’s best to change that to “user://” now before it catches you off-guard when releasing

const SAVE_LOCATION = "user://SAVES/settings.cfg"
func _ready() -> void:
    settings.load(SAVE_LOCATION)
    resolution_index = settings.get_value("Graphic","Resolution")
    #...

func _on_back_fs_pressed() -> void:
    #...
    settings.save(SAVE_LOCATION)

Make sure to format code pastes between three back-ticks ```

Thank you very much. And that includes formatting the code on the forum :3

But it doesn’t work :
I took advantage of what you suggested, but the settings are not saved (I checked in godot itself, exported the project, and launched it)

You may be getting an error when loading or saving the config file, best to check that in code. Can you post what this prints?

const SAVE_LOCATION = "user://SAVES/settings.cfg"
func _ready() -> void:
    var err := settings.load(SAVE_LOCATION)
    print("Loading settings error code: ", error_string(err))

# and the same for settings.save(SAVE_LOCATION)

I’m not quite sure where exactly I should see the results.

In the debugger, I get this

print will show in the output, if you want to see it in the debugger you can use push_warning instead with the same arguments.

image

Assuming your _on_back_fs_pressed is the save function, I’m guessing it’s “File not found” because your save location is in a subdirectory “SAVES/” which may not exist on the user’s computer or yours. You could remove the subdirectory for const SAVE_LOCATION = "user://settings.cfg" or you will have to make it at runtime with DirAccess.

Once this is resolved you can keep the warning, or alert the user only if something is wrong by checking the error code before warning.

var err := settings.load(SAVE_LOCATION)
if err != OK:
    # error! alert the user!
    push_warning("Couldn't load settings config! ", error_string(err))

image
I changed “user://SAVES/settigns.cfg” to “user://settings.cfg”, and now I get this, but the settings don’t seem to be applied from the config

When I found settings.cfg in the user folder, it was empty

Interesting, can you paste your code after the edits? Specifically the parts where you use .set_value and .save?

I’m attaching 2 blocks of code. The only ones related to saving settings

const SAVE_LOCATION = "user://settings.cfg"

var settings = ConfigFile.new()
var resolution_index = 0
var current_display_mode = DisplayServer.WINDOW_MODE_FULLSCREEN
var music_volume_value = -25
var main_theme_index = 0
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	settings.load(SAVE_LOCATION)
	resolution_index = settings.get_value("Graphic","Resolution")
	current_display_mode = settings.get_value("Graphic","Fullscreen")
	music_volume_value = settings.get_value("Graphic","Resolution")
	var err := settings.load(SAVE_LOCATION)
	push_warning("Loading settings error code: ", error_string(err))
	get_node("StartButton").set_visible(1)
	get_node("MainMenuGroup").set_visible(0)
	pass # Replace with function body.

func _on_back_fs_pressed() -> void:
	# Сохраните некоторые значения.
	settings.set_value("Graphic","Fullscreen",current_display_mode)
	settings.set_value("Graphic","Resolution",resolution_index)
	settings.set_value("Sound","MusicVolume",music_volume_value)
	# Сохраните его в файле (перезапишите, если он уже существует).
	settings.save(SAVE_LOCATION)
	var err := settings.save(SAVE_LOCATION)
	push_warning("Loading settings error code: ", error_string(err))
	get_node("SettingsGroup").set_visible(0)
	get_node("MainMenuGroup").set_visible(1)
	pass # Replace with function body.

What does your settings.save method do?

I didn’t understand the question

This method here:

settings.save(SAVE_LOCATION)

What is the code in the save method?

He’s in this block, if you know what I mean

func _on_back_fs_pressed() -> void:
	# Сохраните некоторые значения.
	settings.set_value("Graphic","Fullscreen",current_display_mode)
	settings.set_value("Graphic","Resolution",resolution_index)
	settings.set_value("Sound","MusicVolume",music_volume_value)
	# Сохраните его в файле (перезапишите, если он уже существует).

	settings.save(SAVE_LOCATION)

	var err := settings.save(SAVE_LOCATION)
	push_warning("Loading settings error code: ", error_string(err))
	get_node("SettingsGroup").set_visible(0)
	get_node("MainMenuGroup").set_visible(1)
	pass # Replace with function body.

I placed settings.save on the close button of the settings menu

Oh, I see, you are using the ConfigFile class, my bad.

It seems you’re calling it twice, I don’t think it’s necessary:

settings.save(SAVE_LOCATION)

var err := settings.save(SAVE_LOCATION)

If you print_debug(err), what do you have?

I should see the output from print_debug in the “Debugger”, right? Because it only displays what was there before