这是我的脚本的一个模型:
# 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()
我在这里的目标是让每个球员在轮到他们并输入时都能打印出他们的名字。只有一个玩家的can_play设置为true。在每次输入时,当前玩家的can_play设置为false,下一个玩家的can_pray设置为true。
现在,除了current_player==3之外,此代码每次都能工作。如果在那之后有一个输入;播放器3";以及";播放器0";。Player3和Player0的can_play在只有一个输入的情况下一个接一个地设置为true。其他玩家也不会出现这种情况。
我试着设置了一个Timer,这样代码就不会直接将can_play设置为true,这是成功的。这里真正的问题是,我不明白为什么代码不能只在Player3和Player0 上工作
这是由事件传播引起的。输入事件从最深的叶节点开始在树上冒泡。
解释
Main ^
- Player0 |
- Player1 | _input(event)
- Player2 |
- Player3 |
这种情况是当Player3
can_play
和左键单击输入事件开始在场景树上传播时。
Player3
接收左键点击输入事件。它can_play
,并向Main
发送信号以执行stuff()
。stuff()
将can_play
设置为falsestuff()
将current_player
设置为下一个玩家Player0
- CCD_ 12接收到左键点击输入事件。它不能玩
- CCD_ 13接收到左键点击输入事件。它不能玩
- CCD_ 14接收左键点击输入事件。它CCD_ 15并向CCD_ 16发送信号以执行CCD_ 17。
- 这就是问题所在
- CCD_ 18接收左键点击输入事件
解决方案
处理完输入事件后,调用SceneTree.set_input_as_handled()
。
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")
此处的thing
信号连接应由父级连接。例如:
# Main.gd
func _ready():
for player in players:
player.connect("thing", self, "stuff")
这使Player.gd
与Main.gd
解耦。CCD_ 23不再需要知道方法CCD_ 24。
通常,信号沿着场景树向上,方法调用沿着场景树向下。