How to properly grabbing a moving wall

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By tkon3

Hello, I’m working on a simple 2d platformer.

The player can grab walls by pressing a grab button which does remove gravity and only allow vertical movements, this is working fine.

However I have troubles implementing this feature if the platform is actually moving. Walking on a moving platform works fine but grabbing the “side” of the platform is not working properly in some situations.

To grab walls, I use a horizontal raycast and check collisions, to handle the moving effect, I compute how far the platform did move then I add this difference to the player position. In theory it should work but in some situations it does fail.

If the platform changes its direction and has a significant speed, the player loses the collision and mecanically fall because there is no collision anymore. If I increase significantly the ray size to handle this effect, this won’t happen anymore but the player wont hug the wall in most situations which is not suitable.

I made a toy example with a moving wall and a player. The player starts hugging the wall with the horizontal raycast colliding with the platform. The platform moves horizontally, sometimes changes its direction and increases its speed each time.

Moving Platform script:

    extends KinematicBody2D

var countDistance = 0
var direction = 1
var maxDistance = 500

var motion = Vector2.ZERO
export(int) var speed = 20

func _update_state(delta):
	if countDistance < maxDistance:
		countDistance += delta * speed
	else:
		direction *= -1
		countDistance = 0
		
func _physics_process(delta):
	_update_state(delta)
	
	motion.x = speed*delta*direction
	self.position.x += motion.x
	
	# Increase speed each time until it breaks
	speed += delta*40

Player script:

extends KinematicBody2D

const UP = Vector2(0, -1)
var motion = Vector2.ZERO

func _physics_process(delta):
	if $RayCast2D.is_colliding():
		var collider = $RayCast2D.get_collider()
		self.position += collider.motion
	
	motion = move_and_slide(motion, UP)

The problem is quite obvious, the raycast is not colliding at some point if the platform moves too fast and changes its direction.

How can I prevent this effect or keep hugging the wall at the same time?

Thank you