问题描述
这是我的脚本的模型:
# 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,下一个设置为true。
现在,此代码每次都能工作,除非current_player ==3。如果此后有输入,该代码将同时打印“ Player3”和“ Player0”。 Player3和Player0仅通过一个输入就将can_play设置为true。其他玩家也不会发生这种情况。
我尝试设置一个计时器,以便代码不会直接将can_play设置为true,并且成功。真正的问题是我不明白为什么代码仅在Player3和Player0上不起作用
解决方法
这是由事件传播引起的。输入事件从最深的叶节点开始使树冒泡。
说明
Main ^
- Player0 |
- Player1 | _input(event)
- Player2 |
- Player3 |
情况是Player3
can_play
和左键输入事件开始在场景树中传播。
-
Player3
收到左键输入事件。它can_play
并发信号通知Main
去做stuff()
。-
stuff()
将can_play
设置为false。 -
stuff()
将current_player
设置为下一个玩家Player0
。
-
-
Player2
收到左键输入事件。它无法播放。 -
Player1
收到左键输入事件。它无法播放。 -
Player0
收到左键输入事件。它can_play
并发信号通知Main
进行stuff()
。- 这是问题。
-
Main
收到左键输入事件。
解决方案
处理输入事件后致电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
分离。 Player.gd
不再需要了解方法stuff()
。
通常,信号在场景树上,方法调用在场景树上。