Hello, I'm currently making a grappling hook using my player's arm. The code moves the bones toward the target in three parts (since there are three bones) to stretch them. However, for some completely unknown reason, the arm twists like an accordion. Even if they are oriented straight relative to the shoulder (see the image). To understand better, I invite you to watch the YouTube video.
Thank you for taking the time to help me.
my code :
func _process(_delta: float) -> void:
if is_grappin:
var target_global_pos = grapple_target.global_position
var shoulder_transform = skeleton.get_bone_global_pose(bone_shoulder_idx)
var shoulder_global_pos = skeleton.to_global(shoulder_transform.origin)
var p1 = shoulder_global_pos.lerp(target_global_pos, 0.33)
var p2 = shoulder_global_pos.lerp(target_global_pos, 0.66)
var p3 = target_global_pos
var orient = shoulder_transform.basis
skeleton.set_bone_global_pose_override(bone_arm_idx, Transform3D(orient, skeleton.to_local(p1)), 1.0)
skeleton.set_bone_global_pose_override(bone_forearm_idx, Transform3D(orient, skeleton.to_local(p2)), 1.0)
skeleton.set_bone_global_pose_override(bone_hand_idx, Transform3D(orient, skeleton.to_local(p3)), 1.0)
else:
if bone_arm_idx != -1:
skeleton.set_bone_pose_scale(bone_arm_idx, Vector3(1, 1, 1))
skeleton.reset_bone_pose(bone_arm_idx)
if bone_forearm_idx != -1:
skeleton.set_bone_pose_scale(bone_forearm_idx, Vector3(1, 1, 1))
skeleton.reset_bone_pose(bone_forearm_idx)
if bone_hand_idx != -1:
skeleton.set_bone_pose_scale(bone_hand_idx, Vector3(1, 1, 1))
skeleton.reset_bone_pose(bone_hand_idx)
func _fire_grapple():
var space_state = get_world_3d().direct_space_state
var screen_center = get_viewport().get_size() / 2
var ray_origin = camera.project_ray_origin(screen_center)
var ray_end = ray_origin + camera.project_ray_normal(screen_center) * grapple_range
var query = PhysicsRayQueryParameters3D.create(ray_origin, ray_end)
var result = space_state.intersect_ray(query)
if result:
grapple_hit_point = result.position
grapple_target.global_position = player_hand.global_position
is_grappin = true
var tween = create_tween().set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT)
tween.tween_property(grapple_target, "global_position", grapple_hit_point, grapple_speed)
tween.tween_callback(func():
is_pulling = true
)
tween.tween_interval(0.6)
tween.tween_callback(func():
is_pulling = false
)
tween.tween_property(grapple_target, "position", original_target_pos, grapple_speed)
tween.tween_callback(func():
player_hand.hide()
is_using_hand = false
is_grappin = false
)
Youtube Video :
