godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91.21k stars 21.21k forks source link

GDScript 2.0: Script with function assigned to `@onready` variable generates "tried to assign unset node without an identifier" errors #67085

Closed ababen1 closed 1 year ago

ababen1 commented 2 years ago

Godot version

v4.0.beta2.official [f8745f2f7]

System information

Windows 11, GLES3, NVIDIA GeForce GTX 1650, i5-11300H

Issue description

image

it prints these 2 errors constantly while im writing in that file: Parser bug (please report): Trying to check compatibility of unset value type and modules/gdscript/gdscript_analyzer.cpp:668 - Parser bug (please report): tried to assign unset node without an identifier.

Steps to reproduce

create a new scene and attach this script to the root node

extends Node

@export_file("*.txt") var path_to_words_file: String

@onready var hebrew_words: Dictionary = _create_dict()

func get_random_word() -> String:
    var array = hebrew_words[get_random_letter()]
    return array[randi_range(0, array.size() - 1)]

func get_random_letter() -> String:
    return hebrew_words.keys()[randi_range(0, hebrew_words.keys().size() - 1)]

func save_dictonary(path: String = path_to_words_file) -> void:
    var file = FileAccess.open(path, FileAccess.WRITE)
    var json_string = JSON.stringify(hebrew_words, '\t')
    file.store_string(json_string)

# Create a dictonary with each hebrew letter as keys
func _create_dict() -> Dictionary:
    var file = FileAccess.open(path_to_words_file, FileAccess.READ)
    var hebrew_dict: Dictionary = {}
    for letter in "אבגדהוזחטיכלמנסעפצקרשת":
        hebrew_dict[letter] = []
    while not file.eof_reached():
        var current_word: String = file.get_line()
        current_word = current_word.replacen(",", '')
        current_word = current_word.replacen("\"", '')
        if current_word:
            var current_letter: = current_word[0]
            if current_letter in hebrew_dict.keys():
                hebrew_dict[current_letter].append(current_word)
    return hebrew_dict

Minimal reproduction project

No response

mrbbbaixue commented 2 years ago

Same issue here.

Step to repro:

  1. git clone https://github.com/Bakneko/godot-template.git
  2. Open with godot v4.0.beta2.official.
  3. Run project.

image

derkork commented 2 years ago

Occurs also for this script from the OpenXR tools in beta 3:

v4.0.beta3.mono.official [01ae26d31]

@tool
class_name XRToolsMovementDirect
extends XRToolsMovementProvider

##
## Movement Provider for Direct Movement
##
## @desc:
##     This script provides direct movement for the player. This script works
##     with the PlayerBody attached to the players ARVROrigin.
##
##     The following types of direct movement are supported:
##      - Slewing
##      - Forwards and backwards motion
##
##     The player may have multiple direct movement nodes attached to different
##     controllers to provide different types of direct movement.
##

## Movement provider order
@export var order : int = 10

## Movement speed
@export var max_speed : float = 10.0

## Enable player strafing
@export var strafe : bool = false

## Our directional input
@export var input_action = "primary"

# Controller node
@onready var _controller : XRController3D = get_parent()

func _ready():
    # In Godot 4 we must now manually call our super class ready function
    super._ready()

# Perform jump movement
func physics_movement(_delta: float, player_body: XRToolsPlayerBody, _disabled: bool):
    # Skip if the controller isn't active
    if !_controller.get_is_active():
        return

    # Apply forwards/backwards ground control
    player_body.ground_control_velocity.y += _controller.get_axis(input_action).y * max_speed

    # Apply left/right ground control
    if strafe:
        player_body.ground_control_velocity.x += _controller.get_axis(input_action).x * max_speed

    # Clamp ground control
    var length := player_body.ground_control_velocity.length()
    if length > max_speed:
        player_body.ground_control_velocity *= max_speed / length

# This method verifies the movement provider has a valid configuration.
func _get_configuration_warning():
    # Check the controller node
    var test_controller = get_parent()
    if !test_controller or !test_controller is XRController3D:
        return "Unable to find XR Controller node"

    # Call base class
    return super._get_configu
IkutiDev commented 2 years ago

Using Godot 4 Beta 4 build (non-mono)

Had similar problem with state code from GDQuest course that I ported to Godot 4 and use in my Godot 4 projects.

class_name State
extends Node
@icon("res://assets/core/icons/state.svg")
#State interface to use in Hierarchical State Machines

@onready var _state_machine = _get_state_machine(self)

func unhandled_input(event: InputEvent) -> void:
    return

func physics_process(delta: float) -> void:
    return

func process(delta: float) -> void:
    return

func enter(msg: Dictionary = {}) -> void:
    return

func exit() -> void:
    return

func _get_state_machine(node: Node) -> Node:
    if node != null and not node.is_in_group("state_machine"):
        return _get_state_machine(node.get_parent())
    return node

It also spams the output with the same error if I hold CTRL and move mouse around inside the editor

But I also found out that at least in my case, moving the method that sets the variable onready value above that value inside the script fixes the issue

If I write script like this, the error doesn't seem to appear any more, could be useful workaround until this issue is fixed.

class_name State
extends Node
@icon("res://assets/core/icons/state.svg")
#State interface to use in Hierarchical State Machines

func _get_state_machine(node: Node) -> Node:
    if node != null and not node.is_in_group("state_machine"):
        return _get_state_machine(node.get_parent())
    return node

@onready var _state_machine = _get_state_machine(self)

func unhandled_input(event: InputEvent) -> void:
    return

func physics_process(delta: float) -> void:
    return

func process(delta: float) -> void:
    return

func enter(msg: Dictionary = {}) -> void:
    return

func exit() -> void:
    return
FabIV commented 2 years ago

I also encountered this problem. I tried several things and found out that it seems to be related to @onready variables, that are set to a local function

in this minimum code only my_name2 causes this issue. it is gone as soon as you comment the line out

extends Node2D

@onready var my_name1 = self.name
@onready var my_name2 = get_my_name()

func get_my_name():
    return self.name