0 votes

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
        velocity.x = 0

    var motion = velocity * delta


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.

in Engine by (48 points)
edited by

Please Answer Me.

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

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

The paddle is a KinematicBody2D with child CollisionShape2D and Polygon2D. The code in the paddle simply moves it using moveandcollide 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

func _physics_process(delta):
    velocity = speed * delta * direction
    move_and_collide(Vector2(velocity, 0))
    position.x = clamp(position.x, 0, screensize.x)

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.

1 Answer

0 votes

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 moveandcollide() 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 CCDMODE constants for details.
CCDMODEDISABLED = 0 — Continuous collision detection disabled. This is the fastest way to detect body collisions, but can miss small, fast-moving objects.
CCDMODECAST_RAY = 1 — Continuous collision detection enabled using raycasting. This is faster than shapecasting but less precise.
CCDMODECAST_SHAPE = 2 — Continuous collision detection enabled using shapecasting. This is the slowest CCD method and the most precise.

by (14 points)
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 Frequently asked questions and 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 [email protected] with your username.