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
"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
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
Isn't there any other report about this? This is known for a while but we couldn't yet think of a good solution.
@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.