extends Node3D ## Component for managing physics object holding ## Held object position lerp acceleration. @export var hold_accel := 20.0 ## Held object position velocity scale. @export var hold_speed := 12.0 ## The maximum distance the object may be from the hold point before breaking the hold. @export var max_distance := 3.0 ## Temporary linear damping for held objects @export var hold_damping := 8.0 ## Temporary collision layer. @export_flags_3d_physics var hold_collision_layer := 0 ## Temporary collision mask. @export_flags_3d_physics var hold_collision_physics := 1 ## The object currently being held. var _held_object: RigidBody3D var _original_damping: float var _original_collision_layer: int var _original_collision_mask: int @onready var interact_ray: RayCast3D = %InteractRay @onready var hold_point: Marker3D = %HoldPoint func attach(prop: RigidBody3D, hold_distance: float) -> void: hold_point.position = Vector3(0, 0, -hold_distance) _held_object = prop _original_damping = prop.linear_damp prop.linear_damp = hold_damping _original_collision_layer = prop.collision_layer prop.collision_layer = hold_collision_layer _original_collision_mask = prop.collision_mask prop.collision_mask = hold_collision_physics func drop() -> void: _held_object.linear_damp = _original_damping _held_object.collision_layer = _original_collision_layer _held_object.collision_mask = _original_collision_mask _held_object = null func holding_object() -> bool: return !!_held_object func _physics_process(delta: float) -> void: # Object hold action logic if Input.is_action_just_pressed("interact"): if _held_object: drop() elif interact_ray.is_colliding(): var body := interact_ray.get_collider() as RigidBody3D var hold_component := Holdable.get_component(body) if hold_component: attach(body, hold_component.hold_distance) # Held object logic if not _held_object: return var diff := hold_point.global_position - (_held_object.global_position) if diff.length() > max_distance: drop() return var weight := 1 - exp(-hold_accel * delta) _held_object.linear_velocity = _held_object.linear_velocity.lerp(diff * hold_speed, weight) _held_object.global_basis = _held_object.global_basis.slerp(global_basis, weight)