Creating pin joint dynamically

Godot Version

Godot 3.6

Question

I am trying to create a pin joint between the player and the object when press the grab button. But the pin position is on the centre of the world which i don’t want at all. My character is in a different scene and it loads to the level using code. I tried everything but nothing is working. My character is a rigidbody.

Below is a video example of what is happening

Below is my character scenes tree

Below is my code

“” extends RigidBody2D

=== Constants ===

const GRAVITY_FORCE = 800
const TILT_SPEED = 50
const MAX_TILT_ANGLE = 30
const MAX_JUMP_FORCE = 1000
const MIN_JUMP_FORCE = 0
const JUMP_DECAY_RATE = 1000
const FRICTION = 100
const MAX_SLIDING_SPEED = 200
const COYOTE_TIME = 0.1

const SWING_FORCE = 1500 # Stronger because it’s rigid stick feeling

=== Variables ===

var holding_jump = false
var jump_timer = 0.0
var jump_force_current = MAX_JUMP_FORCE
var current_tilt = 0
var on_ground = false
var was_on_ground = false
var coyote_timer = 0.0

var is_grabbing = false
var grab_point = Vector2()
var pin_joint = null
var grabbed_body = null

=== Nodes ===

onready var anim_player = $AnimationPlayer
onready var spring_bar = $SpringBar
onready var mouth_area = $MouthArea

func _ready():
gravity_scale = 0 # We manually apply gravity

func _process(delta):
_handle_input(delta)

func _physics_process(delta):
if is_grabbing:
_apply_swing_physics(delta)
else:
_apply_gravity(delta)
_update_tilt(delta)
_check_landing()

func _integrate_forces(state):
if not is_grabbing:
_apply_friction(state)

func _handle_input(delta):
if Input.is_action_just_pressed(“jump”) and not is_grabbing:
holding_jump = true
jump_timer = 0.0
jump_force_current = MAX_JUMP_FORCE
anim_player.play(“jump”)
anim_player.seek(anim_player.get_animation(“jump”).length, true)
anim_player.playback_speed = 0

elif Input.is_action_pressed("jump") and holding_jump and not is_grabbing:
	jump_timer += delta
	jump_force_current = max(MIN_JUMP_FORCE, MAX_JUMP_FORCE - JUMP_DECAY_RATE * jump_timer)
	var progress = jump_force_current / MAX_JUMP_FORCE
	var anim_len = anim_player.get_animation("jump").length
	anim_player.seek(anim_len * progress, true)

elif Input.is_action_just_released("jump") and holding_jump and not is_grabbing:
	holding_jump = false
	anim_player.stop()
	anim_player.seek(0, true)

	if on_ground or coyote_timer > 0.0:
		_execute_jump()
	else:
		jump_timer = 0.0
		jump_force_current = MAX_JUMP_FORCE

# Grab input
if Input.is_action_just_pressed("grab"):
	_try_grab()

if Input.is_action_just_released("grab") and is_grabbing:
	_release_grab()

# Update spring bar
spring_bar.value = jump_force_current
spring_bar.modulate = Color.red.linear_interpolate(Color.green, jump_force_current / MAX_JUMP_FORCE)

func _execute_jump():
var tilt_rad = deg2rad(current_tilt)
var jump_direction = Vector2(sin(tilt_rad), -cos(tilt_rad)).normalized()
linear_velocity = jump_direction * jump_force_current

jump_timer = 0.0
jump_force_current = MAX_JUMP_FORCE
coyote_timer = 0.0

func _apply_gravity(delta):
if not on_ground:
linear_velocity.y += GRAVITY_FORCE * delta

func _apply_friction(state):
if on_ground:
var friction_force = Vector2(-linear_velocity.x, 0).normalized() * FRICTION * state.step
linear_velocity += friction_force
linear_velocity.x = clamp(linear_velocity.x, -MAX_SLIDING_SPEED, MAX_SLIDING_SPEED)

func _update_tilt(delta):
var input_dir = Input.get_action_strength(“right”) - Input.get_action_strength(“left”)
current_tilt += input_dir * TILT_SPEED * delta
current_tilt = clamp(current_tilt, -MAX_TILT_ANGLE, MAX_TILT_ANGLE)
rotation_degrees = current_tilt

func _check_landing():
var space_state = get_world_2d().direct_space_state
var ray_start = global_position
var ray_end = global_position + Vector2(0, 10).rotated(rotation)
var result = space_state.intersect_ray(ray_start, ray_end, [self])

on_ground = result.size() > 0
if on_ground:
	coyote_timer = COYOTE_TIME
else:
	coyote_timer -= get_physics_process_delta_time()

func _try_grab():
for body in mouth_area.get_overlapping_bodies():
if body.is_in_group(“grabbable”):
is_grabbing = true
grabbed_body = body
grab_point = mouth_area.global_position
linear_velocity = Vector2.ZERO
_create_pin_joint()
break

func _create_pin_joint():
pin_joint = PinJoint2D.new()
get_parent().add_child(pin_joint)
pin_joint.node_a = get_path()
pin_joint.node_b = grabbed_body.get_path()
pin_joint.position = grab_point

func _release_grab():
is_grabbing = false
if pin_joint and pin_joint.is_inside_tree():
pin_joint.queue_free()
pin_joint = null
grabbed_body = null

func _apply_swing_physics(delta):
# Still apply gravity
linear_velocity.y += GRAVITY_FORCE * delta

# Swing input
var input_dir = Input.get_action_strength("right") - Input.get_action_strength("left")
if input_dir != 0:
	# Apply force sideways relative to bottom (body center)
	var force = Vector2(input_dir * SWING_FORCE, 0)
	apply_impulse(Vector2.ZERO, force * delta)

“”

Please format your code between three tick marks (```) at the top and bottom of your code.

Having said that, my guess is you just need to set your PinJoint’s position to the position of your player and add it as a child of the player.