51 lines
1.6 KiB
GDScript
51 lines
1.6 KiB
GDScript
extends Node3D
|
|
|
|
@onready var pickup_ray: RayCast3D = $PickupRay
|
|
|
|
@export var max_heaviness: float = 30.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)
|