Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GDScript variable chained assignment fails when an intermediate variable is readonly. #41319

Closed
Miziziziz opened this issue Aug 17, 2020 · 6 comments

Comments

@Miziziziz
Copy link

Godot version: 3.2.2

OS/device including version: Windows 10

Issue description:

if you run move_and_collide on a KinematicBody and it collides with something, you can't set a value on the collider you hit, it throws the error:
"invalid set index 'collider' (on base: 'KinematicCollision2D) with value of type 'KinematicBody2D"
the example shown here: https://docs.godotengine.org/en/stable/tutorials/physics/using_kinematic_body_2d.html
does not work

Steps to reproduce:
Have to kinematic bodies next to each other, one has this code:

extends KinematicBody2D

func _physics_process(delta):
	var coll = move_and_collide(Vector2.LEFT * 50)
	if coll and "value_to_set" in coll.collider:
		coll.collider.value_to_set = true

the other has this:

extends KinematicBody2D

var value_to_set = false

Minimal reproduction project:

SetIndexBugKinematic2dColl.zip

@capnm
Copy link
Contributor

capnm commented Aug 17, 2020

"invalid set index 'collider' (on base: 'KinematicCollision2D) with value of type 'KinematicBody2D"

Edit: This works if you create and use a local reference to your collider.

code

extends KinematicBody2D

func _physics_process(_delta):
	var coll: KinematicCollision2D = move_and_collide(Vector2.LEFT * 50)
	if coll != null:
		var c: KinematicBody2D = coll.collider
		#print(c.name)
		if c.name == "Stationary":
			c.value_to_set = true
		if "value_to_set" in c:
			c.value_to_set2 = true
extends KinematicBody2D

var value_to_set := false
var value_to_set2 := false

var once := true
var once2 := true
func _process(_delta):
	if value_to_set and once:
		print("value_to_set:", value_to_set)
		once = false
	if value_to_set2 and once2:
		print("value_to_set2:", value_to_set2)
		once2 = false

@madmiraal
Copy link
Contributor

Interestingly, value_to_set is set to true, the failure occurs afterwards when GDScript then tries to assign the KinematicBody2D to the collider variable and fails, because collider doesn't have a setter. Hence the error message:

Invalid set index 'collider' (on base: 'KinematicCollision2D') with value of type 'KinematicBody2D (Stationary.gd)'.

As @capnm suggested the workaround is to set the value in two lines:

func _physics_process(delta):
	var coll = move_and_collide(Vector2.LEFT * 50)
	if coll and "value_to_set" in coll.collider:
		var c = coll.collider
		c.value_to_set = true

@madmiraal madmiraal changed the title KinematicCollision2D can't directly set values on collider colliding with GDScript variable chained assignment fails when an intermediate variable is readonly. Aug 17, 2020
@madmiraal madmiraal added this to the 3.2 milestone Aug 17, 2020
@vnen
Copy link
Member

vnen commented Sep 1, 2020

Isn't there any other report about this? This is known for a while but we couldn't yet think of a good solution.

@Xrayez
Copy link
Contributor

Xrayez commented Sep 17, 2020

@vnen I think I've stumbled upon exact same issue as described here, I've implemented a LinkedList implementation in goostengine/goost#12 in C++, the LinkedList.front is exposed as a read-only properly (no setter), and to workaround this issue I have to either create intermediate references to front node (or back), or use LinkedList.find().value = "Godot", or by actually calling getter property get_front().value instead.

See detailed bug report at goostengine/goost#17 for more information.

@dalexeev
Copy link
Member

dalexeev commented Feb 16, 2023

Can't reproduce this in RC 2 because the KinematicCollision.collider property has been replaced with the KinematicCollision2D.get_collider() method.

See also:

  • Add error messages in the analyzer when assigning to read-only properties.
  • Add specific error message at runtime when assignment fails because the property is read-only.

I can't say for sure, but judging by the description of the PR, this issue has been fixed in 4.0. Whether we can do something about it in 3.x I don't know.

@akien-mga
Copy link
Member

Tested with this in 4.0 RC 2, it works fine:

	get_tree().root.mode = Window.MODE_FULLSCREEN

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants