I have created and finished my game in Godot, but I want to add a scoring system. Specifically, I want the score to increase by 1 every time the player touches a coin. However, I am not sure how to implement this. Can someone please guide me on how many scenes I need to create and which nodes I need to use? I currently have a scene called ‘coin’ which has an Area2D node
1 Answer
You should not need any more scenes than you have.
I'm going to suggest to do this with a Signal Bus, although it is not the only approach.
Mainly you need to do this:
Create an autoload with an script that has a score variable. So you can access it from anywhere in the scene tree of your game.
extends Node var score := 0
You need to give a name to the autoload, for the purposes of this answer I'll call it
Board
.In a method connected to the body entered signal of your
Area2D
increment the variable. I recommend using a method in a script attached to theArea2D
itself.func _on_coin_body_entered(body) -> void: # ... Board.score += 1
Now, presumably, you don't just want the score to increment. You want to do something with it.
So, I'd suggest you:
Declare a signal to notify when the score changed.
extends Node signal score_changed(score) var score := 0
Then create a setter for the score variable, that emits the signal.
Godot 3
extends Node signal score_changed(score) var score := 0 setget set_score func set_score(mod_value:int) -> void: if score == mod_value: return score = mod_value emit_signal("score_changed", score)
Godot 4
extends Node signal score_changed(score:int) var score := 0: set(mod_value): if score == mod_value: return score = mod_value score_changed.emit(score)
Then you can connect to the signal from anywhere in the scene tree.
Now, what are you going to do with the score?
Presumably you want to show it, right?
So in your UI (I suppose you have an scene for that, or you can add it to one of your scenes) you could add a
Label
and have a script that connects to the signal from the autoload, and when it gets it, it changes the text of the label.Something like this:
Godot 3
extends Label func _ready() -> void: Board.connect("score_changed", self, "_on_score_changed") func _on_score_changed(score:int) -> void: text = str(score)
Godot 4
extends Label func _ready() -> void: Board.score_changed.connect(_on_score_changed) func _on_score_changed(score:int) -> void: text = str(score)
Also presumably you want to store it, right?
So you can add methods to the autoload that save it or load it from storage.
I could give you the code to read and write the score as text alone in a file (you can still find that in the documentation if you want). However, usually we end up wanting to save multiple things in the file. So let me suggest to use the
ConfigFile
class, which will make INI-like files:Godot 3 or Godot 4
const save_file := "user://saved.dat" func load() -> void: var file := ConfigFile.new() var err := file.load(save_file) if err != OK: push_error("error loading score " + str(err)) return score = int(file.get_value("Player", "score")) func save() -> void: var file := ConfigFile.new() file.set_value("Player", "score", score) var err := file.save(save_file) if err != OK: push_error("error saving score " + str(err))
I hope you can see that this approach would work if you need to make a save file for your game, or you need to have a blackboard for the enemies to share information, or you want a configuration file, etc.