My visble workes in one script but refuses in the next

Godot Version

Godot 4

Question

So for some reason witch I don’t understand because I’m new to this it allows me to assign visible and bool in my Control1:


but it gives then I try to do it in my

extends PanelContainer


# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	$VBoxContainer/Button.visable = false
	
	
func _on_save_button_pressed() -> void:
	$VBoxContainer/Button.visible = true

is throws the error
“E 0:00:00:948 _ready: Invalid assignment of property or key ‘visable’ with value of type ‘bool’ on a base object of type ‘Button’.
label.gd:6 @ _ready()
label.gd:6 @ _ready()”

It’s a different scene and all but it should work. Is it because it isnt attached to the top node?

For refrence this is how my other tree lokks like that has the label.gd

You spelled “visible” incorrectly in the _ready() function. You spelled it “visable”. Fix that and it will work.

You can also do this:

extends PanelContainer


# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	$VBoxContainer/Button.hide()
	
	
func _on_save_button_pressed() -> void:
	$VBoxContainer/Button.show()

Or this:

extends PanelContainer

@onready var button = "$VBoxContainer/Button"

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	button.hide()
	
	
func _on_save_button_pressed() -> void:
	button.show()

Thanks, now I feel illiterate haha
I’m ashamed to say how long this was bugging me

Off Topic:
May I ask what the job of the FillButtons is? Do you use them just to give the other buttons some space? I wouldn’t do it that way. I would use the ThemeOverrides - Constants - Separation in the VBoxContainer for this.

I’m petty new so even with that I don’t know if you can do it without an label to distance from.
I also have one more thing, in this:

extends Control

func _ready():
	$CanvasLayer2/Control2.visible = false
	if !FileAccess.file_exists("res://SavedGame.tscn"):
		get_tree().change_scene_to_file("res://main_menu.tscn")
	else:
		var new_scene = ResourceLoader.load("res://SavedGame.tscn")
		get_tree().get_root().add_child(new_scene)
		get_tree().get_root().get_child(0).queue_free()

func _unhandled_input(event: InputEvent) -> void:
	if event.is_action_pressed("Esc"):
		$CanvasLayer2/Control2.visible = true

will this save the scene into a new SavedGame.tscn and then load the scene where you left off playing the game?

You don’t need a label for it to work. The VBoxContainer should line up the buttons just fine. And the separation is the value for how far the buttons are separated.

That’s not how save/load works. You have to serialize every object and on load rebuild them. You can’t write to res:// .

res:// will become locked and un-writeable when you export the game, you should store save data under user:// paths instead. I see no reason why this game would save any data in it’s current state too, preferably you would pick out exactly what you want to save and convert it to a useful save format.

Here’s an official tutorial on creating and loading save data.

Yeah I saw that one but json scared me and has like position and vectors and I’m making more of an click point UI game so I don’t really know how that would work sense I wouldn’t have an “ingame character” in the same sense as a 3D or 2D game :sweat_smile:

Then don’t use JSON, use binary instead. It’s also faster. You just have to keep track of your data and ensure it’s stored and retrieved in a controlled manner.

In Saving and reading data are you supposed to replace all the places that say “node” or is the code supposed to look like that?
And how does json files work and am I shooting myself in the foot if I don’t use it?

It saves all the objects that are in the group “Persist” (in the tutorial). You have to add every object you want to save to this group. For your current state I would use JSON. Maybe read that page a 2nd time. Save/Load can be a little bit confusing the first time. Maybe watch a tutorial on YouTube.

Hahah yeah that’s where I got my old code from and that didn’t go so well

I recommend trying out my Disk Plugin. It’s a documented implementation of that tutorial that allows you to focus on your game, but it’s only a single, short file if you want to understand or expand upon it.

Why does most of the dict give 14 errors of " ERROR: res://the_beginning.gd:13 - Parse Error: Identifier “attack” not declared in the current scope."?

extends Control

func _ready():
	$CanvasLayer2/Control2.visible = false


func save():
	var save_dict = {
		"filename" : get_scene_file_path(),
		"parent" : get_parent().get_path(),
		"pos_x" : position.x, # Vector2 is not supported by JSON
		"pos_y" : position.y,
		"attack" : attack,
		"defense" : defense,
		"current_health" : current_health,
		"max_health" : max_health,
		"damage" : damage,
		"regen" : regen,
		"experience" : experience,
		"tnl" : tnl,
		"level" : level,
		"attack_growth" : attack_growth,
		"defense_growth" : defense_growth,
		"health_growth" : health_growth,
		"is_alive" : is_alive,
		"last_attack" : last_attack
	}
	return save_dict


# Note: This can be called from anywhere inside the tree. This function is
# path independent.
# Go through everything in the persist category and ask them to return a
# dict of relevant variables.
func save_game():
	var save_file = FileAccess.open("user://savegame.save", FileAccess.WRITE)
	var save_nodes = get_tree().get_nodes_in_group("Persist")
	for node in save_nodes:
		# Check the node is an instanced scene so it can be instanced again during load.
		if node.scene_file_path.is_empty():
			print("persistent node '%s' is not an instanced scene, skipped" % node.name)
			continue

		# Check the node has a save function.
		if !node.has_method("save"):
			print("persistent node '%s' is missing a save() function, skipped" % node.name)
			continue

		# Call the node's save function.
		var node_data = node.call("save")

		# JSON provides a static method to serialized JSON string.
		var json_string = JSON.stringify(node_data)

		# Store the save dictionary as a new line in the save file.
		save_file.store_line(json_string)
		

# Note: This can be called from anywhere inside the tree. This function
# is path independent.
func load_game():
	if not FileAccess.file_exists("user://savegame.save"):
		return # Error! We don't have a save to load.

	# We need to revert the game state so we're not cloning objects
	# during loading. This will vary wildly depending on the needs of a
	# project, so take care with this step.
	# For our example, we will accomplish this by deleting saveable objects.
	var save_nodes = get_tree().get_nodes_in_group("Persist")
	for i in save_nodes:
		i.queue_free()

	# Load the file line by line and process that dictionary to restore
	# the object it represents.
	var save_file = FileAccess.open("user://savegame.save", FileAccess.READ)
	while save_file.get_position() < save_file.get_length():
		var json_string = save_file.get_line()

		# Creates the helper class to interact with JSON.
		var json = JSON.new()

		# Check if there is any error while parsing the JSON string, skip in case of failure.
		var parse_result = json.parse(json_string)
		if not parse_result == OK:
			print("JSON Parse Error: ", json.get_error_message(), " in ", json_string, " at line ", json.get_error_line())
			continue

		# Get the data from the JSON object.
		var node_data = json.data

		# Firstly, we need to create the object and add it to the tree and set its position.
		var new_object = load(node_data["filename"]).instantiate()
		get_node(node_data["parent"]).add_child(new_object)
		new_object.position = Vector2(node_data["pos_x"], node_data["pos_y"])

		# Now we set the remaining variables.
		for i in node_data.keys():
			if i == "filename" or i == "parent" or i == "pos_x" or i == "pos_y":
				continue
			new_object.set(i, node_data[i])

Seems like you directly copied and pasted the sample code instead of learning from it. The sample is not designed to work on it’s own, but give examples of how you could store data such as “attack” or “current_health” data. You do not have such variables, so it will fail.

Okay, so if I create the variables, it will solve that problem, thank you

No, if you do not have an “attack” or “defense” in your game then you should remove the line that is trying to save that data, do not add superfluous data to your game just to fill out an arbitrary sample. Your objects save function may only be 4 lines long, it could be very short only saving one variable at a time.

Here’s an example of my shortest save function, this is for a poster, I already know where it’s position is, so I only have to store the selected image.

func on_save() -> Dictionary:
	return { "image_file": filename }