Here's a mock-up of my script:
# player.gd
extends HBoxContainer
class_name Player
var can_play = false
signal thing
func _ready():
connect("thing", #the following script# , "stuff")
func _input(Input):
if !can_play:
return
emit_signal("thing")
# game.gd
extends Node
var players = [Player0, Player1, Player2, Player3] # of class Player
var current_player = 0
func _ready():
yadda()
func yadda():
players[current_player].can_play = true
func stuff():
players[current_player].can_play = false
print(players[current_player])
current_player = (current_player + 1) % 4
yadda()
My goal here is to have each player get their name printed when it's their turn and on input. Only one player should have their can_play set to true. On every input, the current player has their can_play set to false and the next one set to true.
Now this code works every time except when current_player == 3. If there's an input after that, the code prints both "Player3" and "Player0". Player3 and Player0 have their can_play set to true one after the other with only one input. This doesn't happen for the other Players either.
I have tried setting a Timer so that the code doesn't set can_play to true directly and it was successful. The real problem here is that I don't understand why the code wouldn't work only on Player3 and Player0
This is caused by event propagation. Input events bubble up the tree starting from the deepest leaf nodes.
Main ^
- Player0 |
- Player1 | _input(event)
- Player2 |
- Player3 |
The situation is when Player3
can_play
and the left click input event begins propagating up the scene tree.
Player3
receives the left click input event. It can_play
and signals to Main
to do stuff()
.
stuff()
sets can_play
to false. stuff()
sets current_player
to the next player, Player0
. Player2
receives the left click input event. It can't play.Player1
receives the left click input event. It can't play.Player0
receives the left click input event. It can_play
and signals to Main
to do stuff()
.
Main
receives the left click input event. Call SceneTree.set_input_as_handled()
after handling the input event.
if input.is_action_pressed("left_click") and can_play:
emit_signal("thing")
get_tree().set_input_as_handled()
# Player.gd
func _ready():
connect("thing", get_parent(), "stuff")
The thing
signal connection here should be connected by the parent. For example:
# Main.gd
func _ready():
for player in players:
player.connect("thing", self, "stuff")
This decouples Player.gd
from Main.gd
. Player.gd
no longer needs to know about the method stuff()
.
Generally, signals go up the scene tree and method calls go down the scene tree.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.