extends Node3D @onready var pickup_ray: RayCast3D = $PickupRay @export var max_heaviness: float = 20.0 # max object mass allowed @export var hold_distance: float = 3.0 # how far in front of player to hold @export var hold_strength: float = 8.0 # how strongly we pull the object toward target @export var damping: float = 20.0 # smoothness of movement var held_object: RigidBody3D = null func _physics_process(delta: float) -> void: # --- Pickup / Drop toggle --- if Input.is_action_just_pressed("interact"): print("pickup") if held_object: _drop_object() else: _try_pickup() # --- If holding an object, move it toward the target point --- if held_object: _move_held_object(delta) func _try_pickup() -> void: if pickup_ray.is_colliding(): var obj = pickup_ray.get_collider() if obj is RigidBody3D and obj.mass <= max_heaviness: held_object = obj # disable gravity while held (optional) held_object.gravity_scale = 0 func _drop_object() -> void: if held_object: held_object.gravity_scale = 1 held_object = null func _move_held_object(delta: float) -> void: if not held_object: return var target_pos = pickup_ray.global_transform.origin + pickup_ray.global_transform.basis.z * -hold_distance var to_target = target_pos - held_object.global_transform.origin # Smooth velocity-based pulling held_object.linear_velocity = held_object.linear_velocity.lerp(to_target * hold_strength, damping * delta) # Optional: dampen angular spin so object is stable held_object.angular_velocity = held_object.angular_velocity.lerp(Vector3.ZERO, damping * delta)