Gravity changing - unwanted wall friction issue

Godot Version

4.2.2

Question

I’m currently working on a 2d game which uses changing gravity as the only way of moving.
I’ve ran into an issue where the character has unwanted friction near walls which causes it to slow down instead of go straight in one direction.
The walls are made using tilemaps.
I also want the player to keep some of his momentum when changing gravity.

Here’s a video showcasing the issue (spikes aren’t solid yet)(sorry for bad quality):
https://youtu.be/IMgfhVZvSPE

And here’s the code:

extends CharacterBody2D

const GRAVITY = 500
var GravDir = 0 #Down

func _input(event):
	if event.is_action_pressed("Down"):
		GravDir = 0
		%GravfallPlayerSprite.flip_v = false
		%GravfallPlayerSprite.flip_h = false
		%GravfallPlayerSprite.rotation_degrees = 0
		%GravFallPlayerCol.rotation_degrees = 0	
	elif event.is_action_pressed("Up"):
		GravDir = 1
		%GravfallPlayerSprite.flip_v = true
		%GravfallPlayerSprite.flip_h = true
		%GravfallPlayerSprite.rotation_degrees = 0
		%GravFallPlayerCol.rotation_degrees = 0
	elif event.is_action_pressed("Left"):
		GravDir = 2
		%GravfallPlayerSprite.rotation_degrees = -90
		%GravFallPlayerCol.rotation_degrees = -90
		%GravfallPlayerSprite.flip_v = true
	elif event.is_action_pressed("Right"):
		GravDir = 3
		%GravfallPlayerSprite.rotation_degrees = 90
		%GravFallPlayerCol.rotation_degrees = 90
		%GravfallPlayerSprite.flip_v = true

func _physics_process(delta):
	if GravDir == 0: #Down
		velocity.y += delta * GRAVITY
		var motion = velocity * delta
		move_and_collide(motion)
		
	if GravDir == 1: #Up
		velocity.y -= delta * GRAVITY
		var motion = velocity * delta
		move_and_collide(motion)
		
	if GravDir == 2: #Left
		velocity.x -= delta * GRAVITY
		var motion = velocity * delta
		move_and_collide(motion)
		
	if GravDir == 3: #Right
		velocity.x += delta * GRAVITY
		var motion = velocity * delta
		move_and_collide(motion)

Every attempt to help is greatly appreciated :D.

Try using move_and_slide instead, maybe also set your player to motion mode “Floating” in the inspector.

func _physics_process(delta):
	if GravDir == 0: #Down
		velocity.y += delta * GRAVITY
	elif GravDir == 1: #Up
		velocity.y -= delta * GRAVITY
	elif GravDir == 2: #Left
		velocity.x -= delta * GRAVITY
	elif GravDir == 3: #Right
		velocity.x += delta * GRAVITY

	move_and_slide()

move_and_collide stops when it hits any other collision object, it returns information about the collision and it’s intended for you to resolve the collision through code.

1 Like

Thank you!
It works way better now :D.
I kept the player’s motion mode to “Grouded” because “Floating” makes the movement not as fluid when starting from the ground or landing on it.

Also is there a way to control how fast the player slows down after landing?
Currently the surfaces have a very slippery feeling to them which I want to hopefully avoid.

Video for convenience:

You can still detect collisions with get_last_slide_collision, I suppose if the player collides with anything they should start slowing down right?

func _physics_process(delta):
	if GravDir == 0: #Down
		velocity.y += delta * GRAVITY
	elif GravDir == 1: #Up
		velocity.y -= delta * GRAVITY
	elif GravDir == 2: #Left
		velocity.x -= delta * GRAVITY
	elif GravDir == 3: #Right
		velocity.x += delta * GRAVITY

	move_and_slide()

	var collision := get_last_slide_collision()
	if collision: # any collision
		velocity = velocity.move_toward(Vector2.ZERO, delta * FRICTION)
1 Like

It all works amazingly well, thank you so much for the help! :D.