CharacterBody2d sticking to floor/ceiling when sloped

Godot Version

4.2.2

Question

Hello, I have a simple prototype which uses a CharacterBody2d for the player.

The character can hop in the air, flappy bird style, or move horizontally. The player is inside a node2d, which also scrolls forward automatically. ( I originally had the ‘level’ scroll, but found this to be simpler )

However, when the Player collides with sloped surfaces, it becomes ‘stuck’ to it, as if it is being snapped. This will also happen on the ceiling. I’m not sure what is causing this to happen. I’ve set snap to 0. Is there a way to disable this functionality entirely ( it only happens on slopes ).

Here is the setup on the player:

extends CharacterBody2D


const SPEED = 500.0
const JUMP_VELOCITY = -800.0

var gravity = 3000

func _ready():
	self.slide_on_ceiling=false

func _physics_process(delta):
	# Add the gravity.
	if velocity.y>0 and not is_on_floor():
		gravity=700
	else:
		gravity=3000
	if not is_on_floor():
		velocity.y += gravity * delta

	# Handle jump.
	if Input.is_action_just_pressed("ui_up"):
		velocity.y = JUMP_VELOCITY
		print("Pressed Jump!")

	var direction = Input.get_axis("ui_left", "ui_right")
	if direction:
		velocity.x = move_toward(velocity.x, direction * SPEED, 50)
		print("HorizontalMove")
	else:
		velocity.x = move_toward(velocity.x, 0, 80)

	

	if is_on_floor():
		self.modulate=Color.RED
		print("onFloor")
			
	elif is_on_ceiling():
		self.modulate=Color.BLUE
		print("onCeiling")
	else:
		self.modulate=Color.WHITE

	move_and_slide()

The ‘container’ node2D just has a basic update to its position using
self.position += ScrollAmount

I’m attaching a video to help show the problem. Any help would be appreciated!

I tried to recreate this issue locally but am not experiencing it. I set my scene up in a similar way as yours but the character does not stick to the ceiling. Have you changed any other properties of the player or other scene elements?

Thank you so much for taking a look. I haven’t really changed much - on the ‘floor’ parameters, I have ‘max angle 45’ and ‘snap length 0’ This was my attempt to disable it.

I have done some more experimenting, and it seems to have something to do with that fact that the ‘level’ is moving, rather than the player. If I add some constant velocity to the player and have the level static, the sticking doesn’t happen.

So, something about the fact that the ‘level’ is pushing against the player…

That was my original thought as well actually, but I couldn’t recreate the problem, so maybe my setup doesn’t have the issue because of the different sizing/speeds? I agree that it’s related to moving the player without velocity (since move_and_slide() can’t take the direct position updates into account).

I would just apply the constant velocity to the player and the camera directly. Instead of the mover node, just add the scrollAmount to the player’s velocity right before move_and_slide(). You can then move the script from the Mover node to the camera node to have the camera move at a constant velocity.

EDIT:
For convenience, you can have the scroll amount as variables on both the player and camera scripts, then if you want to increase them over time, or have them differ from one level to the next, you can handle that logic in the script for the level and just assign them from there.

Have you tried setting your CharacterBody’s “Motion Mode” to floating?

Thanks for taking a look, I think I’ve come to the same solution as you have. It solves the problem and doesn’t add much in the way of complexity.

Much Appreciated!

Hi! Yes, I did try using the ‘floating’ mode, but that actually made the problem much worse, with some very odd behavior like sudden accelerations.

Thank you for the suggestion!