+2 votes

My player is a KinematicBody2D and when I collide with a block which is also a KinematicBody2D I'd like my player to push it without losing velocity.

My block is in a group called moveables, has no script, and has no other forces acting on it.

After I calculate the velocity of my player in _physics_process(), I have the following code.

# update position and handle collision

var collision = move_and_collide(vel * delta)
if collision:
    var collider = collision.collider
    var normal = collision.normal
    var remainder = collision.remainder
    var collision_angle = rad2deg(acos(normal.dot(Vector2(0,-1))))

    # floors
    if collision_angle == 0:

        # reset y vel so it doesn't keep accumulating
        vel.y = 0

        var horizontal_movement = Vector2(remainder.x, 0)
        move_and_collide(horizontal_movement)

    # moveables
    elif collision_angle == 90:
        if collider in get_tree().get_nodes_in_group("moveables"): 
                collider.move_and_collide(remainder) # move block by remainder
                move_and_collide(remainder) # move player by remainder

This code does allow the player to push the block, but only slowly. I can't figure out why. Ideally, the player would push the block without losing any velocity.

Even if I directly update only the horizontal position of my block, it still moves slower than expected, and my player sprite is blurred, presumably because of collision corrections.

        if collider in get_tree().get_nodes_in_group("moveables"): 
            collider.global_position.x += remainder.x
            move_and_collide(remainder)

The problem seems to be that when I move the player by the remainder, the player is still colliding with the block, even though I move the block itself in the previous line. This is confirmed by analyzing the collision object move_and_collide(remainder).

What's wrong and how can I achieve the desired movement?

Supposing I do achieve my desired movement, how can I then modify the code to make the block harder to push?

in Engine by (1,570 points)
edited by

1 Answer

–5 votes

Why do the movables need to be of type KinematicBody2D? KinematicBody2D is for script motion objects like players, cars, birds, etc. If your movables are physics objects like boxes that can be pushed or thrown balls then you should be using RidgedBody2D.

If you want something like a Player colliding with a NPC and having the NPC be pushed you might want to look into turning a KinematicBody2D into a RidgidBody2D while bumping.

Never use KinematicBody for physics objects unless you really want custom physics. Even then you can modify RidgidBody to do what you want.

by (27 points)

Thanks for the feedback! But how do you suggest pushing a RigidBody2D with a KinematicBody2D? Even if you set mass and friction to very low, it appears the KinematicBody2d still cannot push it. This suggests I would still need to code some collision response similar to what I specify in my question, but calling apply_impulse() or a similar method on the RigidBody2D, rather than move_and_collide() on a KinematicBody2D.

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.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.