简体   繁体   English

脚本忽略设置为 false

[英]Script ignores set to false

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.只有一名玩家应该将他们的 can_play 设置为 true。 On every input, the current player has their can_play set to false and the next one set to true.在每个输入上,当前玩家的 can_play 设置为 false,下一个设置为 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".现在这段代码每次都有效,除非 current_player == 3。如果之后有输入,代码会打印“Player3”和“Player0”。 Player3 and Player0 have their can_play set to true one after the other with only one input. Player3 和 Player0 将它们的 can_play 一个接一个地设置为 true,只有一个输入。 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.我尝试设置一个 Timer 以便代码不会直接将 can_play 设置为 true 并且它成功了。 The real problem here is that I don't understand why the code wouldn't work only on Player3 and Player0这里真正的问题是我不明白为什么代码不能只在 Player3 和 Player0 上工作

This is caused by event propagation.这是由事件传播引起的。 Input events bubble up the tree starting from the deepest leaf nodes.输入事件从最深的叶节点开始向上冒泡。

Explanation解释

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 can_play和左键单击输入事件开始向上传播场景树时。

  1. Player3 receives the left click input event. Player3接收左键单击输入事件。 It can_play and signals to Main to do stuff() .can_play并向Main发出信号来执行stuff()
    • stuff() sets can_play to false. stuff()can_play设置为 false。
    • stuff() sets current_player to the next player, Player0 . stuff()current_player设置为下一个玩家Player0
  2. Player2 receives the left click input event. Player2接收左键单击输入事件。 It can't play.它不能玩。
  3. Player1 receives the left click input event. Player1接收左键单击输入事件。 It can't play.它不能玩。
  4. Player0 receives the left click input event. Player0接收左键单击输入事件。 It can_play and signals to Main to do stuff() .can_play并向Main发出信号来执行stuff()
    • This is the issue.这是问题。
  5. Main receives the left click input event. Main接收左键单击输入事件。

Solution解决方案

Call SceneTree.set_input_as_handled() after handling the input event.处理输入事件后调用SceneTree.set_input_as_handled()

if input.is_action_pressed("left_click") and can_play:
    emit_signal("thing")
    get_tree().set_input_as_handled()

Tip提示

# Player.gd
func _ready():
    connect("thing", get_parent(), "stuff")

The thing signal connection here should be connected by the parent.这里的thing信号连接应该是由父级连接的。 For example:例如:

# Main.gd
func _ready():
    for player in players:
        player.connect("thing", self, "stuff")

This decouples Player.gd from Main.gd .这将Player.gdMain.gd分离。 Player.gd no longer needs to know about the method stuff() . Player.gd不再需要知道方法stuff()

Generally, signals go up the scene tree and method calls go down the scene tree.通常,信号沿场景树向上,方法调用沿场景树向下。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM