(Godot3) When The Ball Hits The Paddle is Paddle Goes Down.

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By keito940
:warning: Old Version Published before Godot 3 was released.

Hi. I’m Breakout Createing Now.
When the ball (RigidBody2D) hits the paddle (KinematicBody2D), the paddle goes down.
The code on the paddle is as follows:

func _physics_process(delta):
	velocity = Vector2()

	if Input.is_action_pressed("ui_left"):
		velocity.x -= speed
	elif Input.is_action_pressed("ui_right"):
		velocity.x += speed
	else:
		velocity.x = 0

	var motion = velocity * delta

	move_and_collide(motion)

Note: Project File: https://drive.google.com/file/d/1f5bLBxjdPeZUL_gwRwMYy-zRJNzX8o_Z/view?usp=sharing
Note2: The code I cited now is the code on the Paddle scene.

Please Answer Me.

keito940 | 2017-12-01 10:52

I am having the same problem.

I’m prototyping a basic ball / brick / paddle game to learn Godot.

I am using KinematicBody2D as per the description in the documentation:

They are not affected by physics at all (to other types of bodies, such a character or a rigid body, these are the same as a static body).

My ball is a simple RigidBody2D with child a child CollisionShape2D and the following basic code for the ball to draw a circle and apply impulse upon game start:

extends RigidBody2D
var released = 0
onready var timer = get_node("label_start/timer_start")

func _draw():
	draw_circle(Vector2(0, 0), 15, Color(255, 0, 0))
	pass

func _input(event):
	if event.is_action_pressed("ui_accept") && timer.time_left == 0 && released == 0:
		released += 1
		apply_impulse(Vector2(0, 0), Vector2(0, 200))
	pass

The paddle is a KinematicBody2D with child CollisionShape2D and Polygon2D. The code in the paddle simply moves it using move_and_collide based upon key inputs:

extends KinematicBody2D

export (int) var speed
var velocity = 0
var input_direction = 0
var direction = 0
onready var screensize = get_viewport_rect().size

func _input(event):
	var move_left = event.is_action_pressed("ui_left")
	var move_right = event.is_action_pressed("ui_right")
	var stop_moving = not (Input.is_action_pressed("ui_right") or Input.is_action_pressed("ui_left"))

	if move_left:
		input_direction = -1
	elif move_right:
		input_direction = 1
	elif stop_moving:
		input_direction = 0
		
	if move_left or move_right or stop_moving:
            direction = input_direction
	pass
	
func _physics_process(delta):
	velocity = speed * delta * direction
	move_and_collide(Vector2(velocity, 0))
	position.x = clamp(position.x, 0, screensize.x)
	pass

Now, as I read it, this should work fine. But when the ball hits the paddle, the paddle is moved as if it were responding to physics, despite the description stating that it shouldn’t.

I’m a novice programmer, looking to move away from Game Maker. So I would appreciate any help, as I’m sure it’s me rather than a bug with Godot. But it does seem to me that the KinematicBody2D is not working as intended, so I’m not sure where to begin.

Cooper42 | 2018-03-26 21:11

:bust_in_silhouette: Reply From: Cooper42

Based upon some comments on another question:

When you use set_pos, the kinematic works as a static (like for use with a moving platform); when you use move, it tries to not overlap while announcing collisions and adjusts its position to a correct one.

The fast rigid may have a little overlap and move() affects the kinematic before the rigid bounces off.

Using move_and_collide() results in the KinematicBody2D moving to avoid overlap. With the ball, this means getting pushed down if the movement commands only involve the x axis.

sing set_pos() is offered as an alternative, but rather than moving smoothly, this ‘teleports’ the paddle around, and can lead to overlap / the rigidbody getting stuck and other bugs.

The solution I have found is to turn on ‘Continuous Collision Detection’ for the RigidBody2D. It comes with a performance impact, but solves the problem.

From the doc:

Continuous collision detection tries to predict where a moving body will collide instead of moving it and correcting its movement after collision. Continuous collision detection is slower, but more precise and misses fewer collisions with small, fast-moving objects. Raycasting and shapecasting methods are available. See CCD_MODE_ constants for details.

CCD_MODE_DISABLED = 0 — Continuous collision detection disabled. This is the fastest way to detect body collisions, but can miss small, fast-moving objects.
CCD_MODE_CAST_RAY = 1 — Continuous collision detection enabled using raycasting. This is faster than shapecasting but less precise.
CCD_MODE_CAST_SHAPE = 2 — Continuous collision detection enabled using shapecasting. This is the slowest CCD method and the most precise.