0
\$\begingroup\$

I was trying to the set up a tile map for a 2D pixel art game in Godot 4.1 (following a tutorial) and realized that there seems to be an issue or something I am not aware of with the way collisions work.

Whenever my character jumps in the -y direction up towards the block, the collision appears to happen a little to early (see pictures), which leads to a very unintuitive experience. But this only happens when approaching the block from -y direction, from any other direction (with varying velocity) the character gets as close as to the block as intended by the collision's shape.

The same occurs when involving the block as CollisionShape2D, instead of a tile map.

What am I missing here?

Character CollisionShape2D

Character not colliding appropriate

Character colliding as intended

Gif jump

Here is the character script:

extends CharacterBody2D

const SPEED = 150.0
const JUMP_VELOCITY = -300.0
const ACCELERATION = 0.25

# This will change, due to the fact that it depends on 
#the ground surface or debufs applied to the character
const AIR_FRICTION = 0.05
const GROUND_FRICTION = 0.6

@onready var animatedSprite2D = $AnimatedSprite2D

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")

func _physics_process(delta):
    
    move_and_slide()
    
    # Add the gravity.
    if not is_on_floor():
        velocity.y += gravity * delta
        velocity.x = lerp(velocity.x, 0.0, AIR_FRICTION)

    # Handle Jump.
    if Input.is_action_just_pressed("ui_accept") and is_on_floor():
        velocity.y = JUMP_VELOCITY

    # Get the input direction and handle the movement/deceleration.
    var direction = Input.get_axis("ui_left", "ui_right")
    
    if direction:
        set_facing_direction(direction)
        velocity.x = lerp(velocity.x, direction * SPEED, ACCELERATION)
        animatedSprite2D.play("Run")
    else:
        velocity.x = lerp(velocity.x, 0.0, GROUND_FRICTION)
        animatedSprite2D.play("Idle")

func set_facing_direction(direction):
    if(direction > 0):
        animatedSprite2D.flip_h = true
    if(direction < 0):
        animatedSprite2D.flip_h = false
\$\endgroup\$
6
  • \$\begingroup\$ Does Godot handle collisions for you? Is there a chance Godot calculated that from one frame to the next, the character has collided and moved slightly down, presumably because the timestep was high enough? If that's the case, there's nothing wrong with it. If you could post something animated it might make it easier to see how the collision behaves. \$\endgroup\$ Commented Nov 28, 2023 at 14:38
  • \$\begingroup\$ I added a gif of what is happening. Hopefully it helps. \$\endgroup\$
    – JAL
    Commented Nov 29, 2023 at 10:35
  • \$\begingroup\$ Btw. about the timestep, I didn't adjust the tick-rate, thus it's default I guess. \$\endgroup\$
    – JAL
    Commented Nov 29, 2023 at 10:45
  • \$\begingroup\$ Is it possible that the object is colliding and rebounding a short distance away in the same frame, making it look like it stopped early? Do you have any control over physics/material settings where you and adjust a "bounciness" or "restitution" strength to see if that changes the observed gap? \$\endgroup\$
    – DMGregory
    Commented Nov 29, 2023 at 13:36
  • \$\begingroup\$ @DMGregory hmm, I don't know. Wouldn't it be the case that the rebound appears to be different everytime, depending on how long the current frame already lasted? Or would it move the transform instantly.. Anyway, I played with the "physics/2d/solver/contact_max_allowed_penetration" property, for which it says "Maximum distance a shape can penetrate another shape before it is considered a collision". But not much changed. \$\endgroup\$
    – JAL
    Commented Nov 29, 2023 at 16:29

0

You must log in to answer this question.

Browse other questions tagged .