+1 vote

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?

asked Feb 21, 2019 in Engine by Lovax (16 points)

1 Answer

+1 vote
Best answer

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.

answered Feb 21, 2019 by RenenerG (246 points)
selected Feb 22, 2019 by Lovax

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))

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!

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.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.