How to get one KinematicBody2D to push another?

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

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?

:bust_in_silhouette: Reply From: CensedPie

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.

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.

Diet Estus | 2018-12-20 05:52