脚本忽略设置为false

问题描述

这是我的脚本的模型:

# 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和左键输入事件开始在场景树中传播。

  1. Player3收到左键输入事件。它can_play并发信号通知Main去做stuff()
    • stuff()can_play设置为false。
    • stuff()current_player设置为下一个玩家Player0
  2. Player2收到左键输入事件。它无法播放。
  3. Player1收到左键输入事件。它无法播放。
  4. Player0收到左键输入事件。它can_play并发信号通知Main进行stuff()
    • 这是问题。
  5. 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.gdMain.gd分离。 Player.gd不再需要了解方法stuff()

通常,信号在场景树上,方法调用在场景树上。