KinematicBody get stuck on walls until opposite direction is pushed

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Lovax

I have a KinematicBody (the ship) with a round collision shape. There is a wall on its left, a StaticBody with a plane collision shape.

The ship is moving towards the wall, the red array is the input velocity:

enter image description here

But when I hit the wall, as long as my X velocity is < 0, I can’t move, even on the Y axis.
To move along Y, I need to cancel any movement along -X. It is just like there was a huge friction coefficient between the two bodies.

However the friction coefficient of the StaticBody of the wall is set to 0…

What I want is the wall to block any translation on the X axis only but let the Y axis free.

What can I do?

:bust_in_silhouette: Reply From: RenenerG

TL;DR:

According to this Issue on GitHub, this is discussed as normal behaviour.


Hello Lovax,

which method of the KinematicBody do you use for moving it?
Have you tried move_and _slide?

“Moves the body along a vector. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a KinematicBody or RigidBody, it will also be affected by the motion of the other body. You can use this to make moving or rotating platforms, or to make nodes push other nodes.”

It sounds like this would fix your problem.

According to the description, move_and _collide would stop your KinematicBody immediately if it collides.

I am already using move_and_slide, here is my code to process the movement of the KinematicBody:

func process_movement(delta):
    # dir is the body's basis dot the input movement vector
	dir = dir.normalized() 
	
	if dir.x == 0:
		if vel.x > 0:
			vel.x = max(vel.x - DEACCEL*delta, 0)
		else:
			vel.x = min(vel.x + DEACCEL*delta, 0)
	else:
		vel.x += ACCEL*delta*dir.x
		
	if dir.y == 0:
		if vel.y > 0:
			vel.y = max(vel.y - DEACCEL*delta, 0)
		else:
			vel.y = min(vel.y + DEACCEL*delta, 0)
	else:
		vel.y += ACCEL*delta*dir.y
		
	if dir.z == 0:
		if vel.z > 0:
			vel.z = max(vel.z - DEACCEL*delta, 0)
		else:
			vel.z = min(vel.z + DEACCEL*delta, 0)
	else:
		vel.z += ACCEL*delta*dir.z
	
	vel = move_and_slide(vec3clamp(vel, -MAX_SPEED, MAX_SPEED))

Lovax | 2019-02-22 09:08

So according to this Issue on GitHub. It seems to be normal behaviour.

They basically said, that you cant use plane mesh with plane collider in combination with KinematicBodys.
So your solution would be to use something other than planes. Read the issue for more information.

I recreated a simple scene similar to yours and can confirm that.


Here is my Player script for a KinematicBody, if you need a comparison.

export var speed = 10

var velocity = Vector3(0,0,0)

func _physics_process(delta):

    velocity = move_and_slide(velocity)

    var direction = Vector3(0,0,0)

    if Input.is_action_pressed("move_down"):
        direction.y -= 1
    if Input.is_action_pressed("move_up"):
        direction.y += 1
    if Input.is_action_pressed("move_left"):
        direction.x -= 1
    if Input.is_action_pressed("move_right"):
        direction.x += 1

    var motion = direction.normalized() * speed

    velocity.x = lerp(velocity.x, motion.x, 0.2)
    velocity.y = lerp(velocity.y, motion.y, 0.2)

Good Luck!

RenenerG | 2019-02-22 10:04

Understood, I replaced my plane shapes by boxes and it worked as expected. This is quite strange though, in UE4 we usually use plane collisions for invisible walls.

Lovax | 2019-02-22 10:53