I am making a 3d endless runner game. but the problem lies in collecting the coin.
I want to display the coins that are collected by the player.
This is my label script:
This is my Globalscript:
This is my Coin script:
I was expecting that if i collected a coin. my coin display would display how many coins I have collected.
so far, my collision shapes and the coin detect each other as it shows "collected" on my output :
For what I gather there are two "body_entered" signals:
Global_Coin
(I'm taking it is an autoload) has a _on_body_entered
signal defined, which passes no arguments:
extends Node
signal _on_body_entered
Then in your Area3D
you connect it to the _on_body_entered
method.
And it would be emitted by the Label
of all things, from the _on_body_entered
method which I believe is not called at all.
The Area3D
has a body_entered
that has a body:Node3D
parameter.
This signal would be emitted by the Area3D
when some body enters it.
And I'm guessing is connected to the _on_body_entered
method by other means, which explains how the "collected"
message shows up in output.
Note: I'm confident that the body_entered
signal of the Area3D
is not connected to the _on_body_entered
of the Label
because that method has no parameters, and thus you would have an error if it were connected, given that the body_entered
signal from Area3D
passes an argument.
Thus:
Pick different names for different things. Otherwise you will end up confusing whoever reads your code, which most of the time is yourself (which I believe is the case here).
Single responsibility principle: The job of the Label
is to display text. Why is the Label
responsible from emitting a signal (and of "body entered" of all things)? It should not be emitting a signal for this (that is not its responsibility). In fact, it makes more sense that it would be receiving it.
The following is what makes sense:
Make sure the body_entered
signal of the Area3D
is connected to the _on_body_entered
method in the scrip attached to the same Area3D
. I believe this is already the case, but I do not see the usual green icon that indicates the connection, thus I suggest to double check.
Have the _on_body_entered
method in the Area3D
emit the _on_body_entered
signal from Global_Coin
. In fact, I'd suggest to change the name of the signal to something more meaningful, e.g. coin_collected
.
Connect from code the _on_body_entered
signal from Global_Coin
to the _on_body_entered
method in the Label
(currently you do this in the Area3D
), so the Label
can increment its count.
In general the flow of data would be like this:
Area3D
Area3D
emits its Area3D.body_entered
signal.Area3D
handles the Area3D.body_entered
signal, and emits the Global_Coin._on_body_entered
signal, and also queues itself from removal.Global_Coin._on_body_entered
signal and increments its count. I'll insist in renaming the singal.Furthermore, we can put a setter on coins
instead of calling _ready
.
Thus:
Global_Coin:
extends Node
signal coin_collected
Area3D:
extends Area3D
func _on_body_entered(body:Node3D) -> void:
prints("collected")
Global_Coin.coin_collected.emit()
queue_free()
Label:
extends Label
var coins:int = 0:
set (mod_value):
coins = mod_value
text = str(coins)
func _ready() -> void:
Global_Coin.coin_collected.connected(_on_coin_collected)
# coins = 0
func _on_coin_collected() -> void:
coins = coins + 1