简体   繁体   中英

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. 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.

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.

  1. 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 .
  2. Player2 receives the left click input event. It can't play.
  3. Player1 receives the left click input event. It can't play.
  4. Player0 receives the left click input event. It can_play and signals to Main to do stuff() .
    • This is the issue.
  5. Main receives the left click input event.

Solution

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()

Tip

# 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.

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