using UnityEngine; using UnityEngine.InputSystem; public class ItemPickup : MonoBehaviour { [Header("Layer Settings")] public LayerMask pickupLayer; [Header("Input Settings")] public InputActionAsset inputActionAsset; [Header("Pickup Settings")] public float pickupSpeed = 10f; // How fast it snaps to your hand public float holdDistance = 3f; // Default distance private InputAction pickUpAction; private Camera mainCamera; // We store the Rigidbody instead of the GameObject private Rigidbody currentPickedRB = null; void Awake() { mainCamera = Camera.main; } private void OnEnable() { if (inputActionAsset != null) { pickUpAction = inputActionAsset.FindAction("PickUp"); if (pickUpAction != null) { pickUpAction.Enable(); pickUpAction.started += OnPickUpStarted; pickUpAction.canceled += OnPickUpCanceled; } } } private void OnDisable() { if (pickUpAction != null) { pickUpAction.started -= OnPickUpStarted; pickUpAction.canceled -= OnPickUpCanceled; pickUpAction.Disable(); } } private void OnPickUpStarted(InputAction.CallbackContext context) { // 1. Raycast to find object Vector2 mousePos = Mouse.current.position.ReadValue(); Ray ray = mainCamera.ScreenPointToRay(mousePos); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { // Check if it has a Rigidbody and match layer if (hit.collider.TryGetComponent(out Rigidbody rb) && ((1 << hit.collider.gameObject.layer) & pickupLayer) != 0) { currentPickedRB = rb; // --- CRITICAL FIX START --- // If we pick it off a Shelf, it is frozen (Kinematic). // We must unfreeze it immediately so we can apply velocity. currentPickedRB.isKinematic = false; // --- CRITICAL FIX END --- // 2. Setup Physics for "Holding" currentPickedRB.useGravity = false; // Add damping so it doesn't drift around like it's on ice currentPickedRB.linearDamping = 10; currentPickedRB.angularDamping = 5; // Optional: Calculate distance to keep it where we clicked holdDistance = hit.distance; // Notify RayCastSystem RayCastSystem rayCastSystem = GetComponent(); if (rayCastSystem != null) { rayCastSystem.SetCurrentPickedRB(rb); } } } } private void OnPickUpCanceled(InputAction.CallbackContext context) { if (currentPickedRB != null) { // 3. Reset Physics properties currentPickedRB.useGravity = true; currentPickedRB.linearDamping = 0; // Reset to default (usually 0) currentPickedRB.angularDamping = 0.05f; currentPickedRB = null; // Notify RayCastSystem that an object is no longer picked up RayCastSystem rayCastSystem = GetComponent(); if (rayCastSystem != null) { rayCastSystem.SetCurrentPickedRB(null); } } } // Physics movement must be in FixedUpdate private void FixedUpdate() { if (currentPickedRB != null) { MoveObjectPhysics(); } } private void MoveObjectPhysics() { Vector2 mousePos = Mouse.current.position.ReadValue(); Ray ray = mainCamera.ScreenPointToRay(mousePos); // Where we want the object to be Vector3 targetPosition = ray.GetPoint(holdDistance); // Calculate direction vector: Target - Current Vector3 direction = targetPosition - currentPickedRB.position; // Apply Velocity // We multiply by pickupSpeed to make it responsive // The physics engine handles the rest (Mass 1 vs Mass 100 collisions) currentPickedRB.linearVelocity = direction * pickupSpeed; // Note: In Unity versions older than 2023.3, use 'velocity' instead of 'linearVelocity' // currentPickedRB.velocity = direction * pickupSpeed; } }