Files
ShopGame/Assets/Scripts/ItemPickup.cs
2025-12-17 17:34:04 +00:00

138 lines
4.4 KiB
C#

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<RayCastSystem>();
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<RayCastSystem>();
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;
}
}