Grappling mechanic bug

Godot Version

Godot 4.2.1

Question

Im making a grapple-up your way kinda game. I have used a character with characterbody2d. the player has a grapple mechanic node on him. the grapple manager code , uses a ray cast 2d to check for surrounding collisions and if it matches a valid surface , when the player clicks grapple button , he grapples to it. The problem im facing is that , someitmes , whilst falling and trying to latch on to a valid surface , the player grapples on to empty air. idk the exact reason behind this bug. The image shows the bug.

THE CODE :

@onready var player : CharacterBody2D = get_parent() 
@onready var ray : RayCast2D = $RayCast2D
@onready var launched = false
@onready var target : Vector2
@onready var rope = $Line2D
@export var rest_len = 2.0
@export var stiffness = 10.0
@export var damping = 2.0
@onready var hook = $"../GrappleHook"

func _ready():
	Input.mouse_mode = Input.MOUSE_MODE_HIDDEN

func _process(delta):
	
	hook.global_position = get_global_mouse_position()
	if ray.is_colliding():
		hook.modulate = "6fffbbb5"
	else:
		hook.modulate = "ffffffd9"
	ray.look_at(get_global_mouse_position())
	if Input.is_action_just_pressed("GRAB"):
		if ray.is_colliding():
			launch()
	
	if Input.is_action_just_released("GRAB"):
		retract()
	
	if launched:
		handle_grapple()

func launch():
	if ray.is_colliding():
		
		target = ray.get_collision_point()
		if target:
			launched = true
			rope.show()

func retract():
	launched = false
	rope.hide()
	
func handle_grapple():
	
	if target :
		var target_dir = player.global_position.direction_to(target)
		var target_dist = player.global_position.distance_to(target)
		var displacement = target_dist - rest_len
	
		var Force = Vector2.ZERO
	
		if displacement > 0:
			update_rope()
			var spring_force_magnitude = stiffness * displacement
			var spring_force = target_dir * spring_force_magnitude
		
			var vel_dot = player.velocity.dot(target_dir)
			var damping = -damping * vel_dot * target_dir
		
			Force = spring_force + damping
		
		player.velocity += Force

	
func update_rope():	
		rope.set_point_position(1,to_local(target))
	
	

Please post your code (as pre-formatted text. i.e. place three backticks (```) before and after your code.) Without seeing your code, the best people can do is make (bad) guesses.

1 Like

You should post the grapple code.

i have attached the code now

its there now XD

Try adding check if grapple is launched to your input action checks:

if Input.is_action_just_pressed("GRAB") && !launched:
...
if Input.is_action_just_released("GRAB") && launched:
...

You also don’t need if ray.is_colliding(): in your launch function since it’s checked before calling it.

I updated these line. The problem still persists. I feel like , the problem is being caused by the fact that , the ray collides and marks the point to be a valid hit , but then ,the player is probably falling too fast that the collision point is missing as he falls down , but the grab button is pressed , so the system now since it lost its grapple collision point , just grapples onto empty air. Im not sure if its right , but regardless , Thankyou for your support XD

I don’t know how grappling work in your code, but maybe make player “hang” in air if grappling successful? That what i mostly seen in 2D games. So disabling gravity even for couple frames may help.