The error is that move_and_slide
is an instance method. Thus, calling it like an static method (from the class name, i.e. KinematicBody.move_and_slide(…)
) does not work.
Usually, you want to setup your nodes like this:
KinematicBody
├ MeshInstance
└ CollisionShape
The idea is that the MeshInstance
moves according to how the KinematicBody
moves, so you make it a child of it. You want to move the KinematicBody
(with move_and_slide
) and have the MeshInstance
follow, and not the other way around. Because it is responsibility of KinematicBody
to interact with physics, while the responsibility of MeshInstance
is to interact with graphics.
About where to call move_and_slide
, the recommendation is to have a script in your KinematicBody
that looks something like this:
extends KinematicBody
func _physics_process(delta:float)-> void:
# …
move_and_slide(…)
# …
Of course, it is possible to manipulate the the KinematicBody
externally. You first need to get a reference to it (using get_node
, for example), because - again - it is not an static method. You could have multiple KinematicBody
, and which one are you moving? (rhetoric).
Also, move_and_slide
is meant to be called in the physics step (remember it will move a physic object, and also it handles collision - which is the slide part), which is why I put it in _physics_process
.
To save you some other gotchas, some advice:
- The method
move_and_slide
takes velocity, not distance, and thus you don't need to multiply by delta
to call it. Which isn't the case with move_and_collide
.
- The values of
is_on_wall
, is_on_floor
and is_on_ceiling
are updated when move_and_slide
runs (the up vector you pass as second parameter is used to decide what is a wall, floor, or ceiling). As consequence I recommend to query them (and anything else you query, including Input
and collisions) after the call to move_and_slide
, so you have updated values. The only thing I place before calling move_and_slide
is applying gravity (if the game needs gravity).
- It is usually a bad idea to reference up the scene tree. In particular, if you make an scene for instancing, that scene has no control over where it gets instanced. So avoid referencing outside of the current scene. If you always reference down, then you never have to worry about it when converting a branch into a scene. Instead, when you want to communicate upwards, use signals. The exception is referencing autoloads, which are available everywhere, and survive scene transitions. On that node, know it can useful to put signals on autoloads, so you can connect to them everywhere.
And have some linky links: