Need some help with movable physics objects

i want to make a first person game (maybe a shooter or something), and i was trying to make some logic for picking cubes up and it did work out eventually but there is some uhh unintended behaviour that i don’t want to happen, specifically:

problem number 1: when i pick up the cube, it tries to get to a position 2.5 units away from camera, cancels all rotations and faces the camera. if there are objects that it can collide with in that place, it tries to move closer to the player until it does not collide with anything. but, after the collision, if it has rotated or moved above or below the target point, it sometimes gets stuck in that position (above or below the point that it should be at + rotated slightly).

example pictures:

and that’s not even the worst position, sometimes it even doesnt touch the dot in the middle and stays above it (or below)

here’s the code that is responsible for moving the cube when it is picked:

updates:

    void FixedUpdate()
    {
        if (isPickedUp)
        {
            MoveCubeWithPlayer(); // This function deals with moving the object that i have picked up
            lastVelocity = (transform.position - previousPosition) / Time.fixedDeltaTime;
            previousPosition = transform.position; // These two lines are necessary to be able to throw cubes
        }
    }

Moving the cube:

    void MoveCubeWithPlayer()
    {
        float maxDistance = 2.5f; // The distance that it tries to put the cube at, at first
        float minDistance = 0.1f; // Minimal distance, when reached the cube is dropped (tried to prevent the second problem with this)
        float targetDistance = maxDistance;
        float decrementStep = 0.1f; // If cube collides with something, it goes closer to the player by this distance every frame? not sure

        Vector3 direction = playerCamera.transform.forward;
        Vector3 targetPosition = playerCamera.transform.position + direction * targetDistance;

        int layerMask = ~(LayerMask.GetMask("Player") | LayerMask.GetMask("MovableObj")); // The layers that are being ignored by raycast

        RaycastHit hit;
        if (Physics.Raycast(playerCamera.transform.position, direction, out hit, maxDistance, layerMask))
        {
            targetPosition = hit.point - direction * 0.05f;
        }

        while (targetDistance > minDistance && Physics.CheckBox(targetPosition, cubeCollider.bounds.extents, Quaternion.identity, layerMask))
        {
            targetDistance -= decrementStep;
            targetPosition = playerCamera.transform.position + direction * targetDistance;
        }

        if (targetDistance < minDistance)
        {
            DropCube(); // Drop the cube if it gets too close to the player (want to replace it later but it somewhat prevents the second problem)
            return;
        }

        Vector3 lookAtPoint = playerCamera.transform.position;
        Quaternion targetRotation = Quaternion.LookRotation(lookAtPoint - transform.position);
        targetRotation = Quaternion.Euler(0, targetRotation.eulerAngles.y, 0); 

        rb.MovePosition(Vector3.Lerp(transform.position, targetPosition, Time.fixedDeltaTime * smoothSpeed));
        rb.MoveRotation(Quaternion.Lerp(transform.rotation, targetRotation, Time.fixedDeltaTime * smoothSpeed));

        Debug.Log($"Target Position: {targetPosition}, Target Rotation: {targetRotation.eulerAngles}, RBVelocity: {rb.velocity}, LastVelocity: {lastVelocity}");
    }

problem number 2: the player can push cubes into walls and into eachother. i have no idea how to fix it or what to do with it at all. if i take a cube and try to walk into a wall while holding it, it can go through the wall if i walk fast enough. happens even more often while the player is sprinting. in order to somewhat fix it i made it so that if the cube is too close to the player, it is dropped, but first, it doesnt always help, second, it sometimes makes the player drop the cube even when it is not being pushed into a wall or anything, just too close to the player(or when rotating the camera too quickly, the cube tries to go directly through the player and drops), and thirdly it does not prevent pushing cubes into cubes. also if i get the cube around the wall and move backwards it would go through the wall

problem number 3: i can jump on a cube, pick it up and jump on it repeatedly to fly. it is somewhat fixed by the dropping of the cube if it gets too close to the player, but it seems kind of an annoying fix to me, i as a player would not like the fact that the stuff i pick up can just randomly drop bc it got too close to my character

full code for the movable objects (cubes):


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeController : MonoBehaviour
{
    public Transform player;
    public Camera playerCamera;
    public float moveDistance = 2.0f;
    public float pickupDistance = 3.0f;
    public float smoothSpeed = 10.0f;
    private bool isPickedUp = false;
    private Rigidbody rb;
    private Collider cubeCollider;
    private Vector3 lastVelocity;
    private Vector3 previousPosition;
    private int layerMask;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        cubeCollider = GetComponent<Collider>();
        layerMask = ~LayerMask.GetMask("MovableObj");
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.E))
        {
            if (isPickedUp)
            {
                DropCube();
            }
            else
            {
                TryPickupCube();
            }
        }
    }

    void FixedUpdate()
    {
        if (isPickedUp)
        {
            MoveCubeWithPlayer();
            lastVelocity = (transform.position - previousPosition) / Time.fixedDeltaTime;
            previousPosition = transform.position;
        }
    }

    void OnCollisionExit(Collision collision)
    {
        rb.velocity = Vector3.zero;
    }

    void TryPickupCube()
    {
        Vector3 rayOrigin = playerCamera.transform.position;
        Vector3 rayDirection = playerCamera.transform.forward;
        RaycastHit hit;
        float sphereRadius = 0.02f;

        if (Physics.SphereCast(rayOrigin, sphereRadius, rayDirection, out hit, pickupDistance))
        {
            if (hit.transform == transform)
            {
                PickupCube();
            }
        }
    }

    void PickupCube()
    {
        isPickedUp = true;
        rb.useGravity = false;
        rb.collisionDetectionMode = CollisionDetectionMode.Continuous;
        cubeCollider.enabled = true;
        rb.velocity = Vector3.zero;
    }

    void DropCube()
    {
        isPickedUp = false;
        rb.useGravity = true;
        rb.collisionDetectionMode = CollisionDetectionMode.Discrete;
        cubeCollider.enabled = true;
        rb.velocity = lastVelocity;
    }

    void MoveCubeWithPlayer()
    {
        float maxDistance = 2.5f;
        float minDistance = 0.1f;
        float targetDistance = maxDistance;
        float decrementStep = 0.1f;

        Vector3 direction = playerCamera.transform.forward;
        Vector3 targetPosition = playerCamera.transform.position + direction * targetDistance;

        int layerMask = ~(LayerMask.GetMask("Player") | LayerMask.GetMask("MovableObj"));

        RaycastHit hit;
        if (Physics.Raycast(playerCamera.transform.position, direction, out hit, maxDistance, layerMask))
        {
            targetPosition = hit.point - direction * 0.05f;
        }

        while (targetDistance > minDistance && Physics.CheckBox(targetPosition, cubeCollider.bounds.extents, Quaternion.identity, layerMask))
        {
            targetDistance -= decrementStep;
            targetPosition = playerCamera.transform.position + direction * targetDistance;
        }

        if (targetDistance < minDistance)
        {
            DropCube();
            return;
        }

        Vector3 lookAtPoint = playerCamera.transform.position;
        Quaternion targetRotation = Quaternion.LookRotation(lookAtPoint - transform.position);
        targetRotation = Quaternion.Euler(0, targetRotation.eulerAngles.y, 0); 

        rb.MovePosition(Vector3.Lerp(transform.position, targetPosition, Time.fixedDeltaTime * smoothSpeed));
        rb.MoveRotation(Quaternion.Lerp(transform.rotation, targetRotation, Time.fixedDeltaTime * smoothSpeed));

        Debug.Log($"Target Position: {targetPosition}, Target Rotation: {targetRotation.eulerAngles}, RBVelocity: {rb.velocity}, LastVelocity: {lastVelocity}");
    }

}

this script is attached to all movable objects

if someone can help i would really appreciate it. thx in advance