138 lines
4.4 KiB
C#
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;
|
|
}
|
|
} |