Object moving through walls when I scroll the mouse wheel to alter its position

I have implemented code where a player can pick up an item, and move it closer and further away by using the scrollwheel on the mouse. I thought this was working fine, as the player cant move the object too far away, nor can they move it too close. However, my problem is that while scrolling the mouse wheel, the player can scroll the object through the wall, or through other items.

If I have the object held, and I walk into another object, such as a door or wall or something, its fine. The object doesnt pass through it. However if I stand by a door and scroll the mouse wheel to move the object further away, it can pass through the door.

I feel that when I alter the objects position in the code used to move the held object, that this is somehow over riding something and causing the objects to be able to be moved through colliders when the scroll wheel is being used.

Here is a 9 second video of the problem

http://gfycat.com/LoneSpitefulArawana

Any help / advise would be greatly appreciated.

void HoldObject(GameObject heldObject)
    {
        distance = distance + Input.GetAxis ("Mouse ScrollWheel"); //float distance refers to how far away the object is away from the player

        if (distance > maxDistance) { //This prevents the player from constantly scrolling the wheel to move the object really far away
            distance = maxDistance;
        }
       
        if (distance < minDistance) { //This prevents the player from constantly scrolling the wheel to move the object back through the players body
            distance = minDistance;
        }

/*Here I set the object being held position to where the camera is looking (i.e in front of the player), and I then modify how close / far away that is based on the distance variable which is taken from the mouse wheel. So scrolling the object modifies its position by bringing the held object closer and further away.
*/

        heldObject.transform.position = Vector3.Lerp (heldObject.transform.position, mainCamera.transform.position + mainCamera.transform.forward * distance, Time.deltaTime * smooth); 

        if (!Input.GetMouseButton (1)) { //If you are not holding down right click, set the object rotation to its identity. Holding right click rotates the object.
            heldObject.transform.rotation = Quaternion.identity;
        } else {
            heldObject.transform.Rotate(Vector3.up * Time.deltaTime * 300); //Else you must be holding right click, so rotate the held object
        }
    }

You are setting the position of the object. This bypasses the physics system. You will need to manipulate the object using physics. Im sure you can find some implementations searching for drag rigidbody or carry rigidbody.

I guessed that that was the issue in some way. I just cant seem to think of an intuitive way to move the object that prevents it from doing this. I did try this :

heldObject.transform.GetComponent<Rigidbody>().transform.position = Vector3.Slerp (heldObject.transform.GetComponent<Rigidbody>().transform.position, mainCamera.transform.position + mainCamera.transform.forward * distance, Time.deltaTime * smooth);

However it has the same result

you’re still directly altering the position of the tranform (you’re just getting the transform’s reference in a roundabout way).

in order to move something within the physics system you need to use one of the Rigidbody’s functions

1 Like

Yes, because that is the same thing you are doing. Just that youre passing through a lot of components getting to the same Transform.

Yup, a transform’s rigidbody’s transform isn’t different from the transform itself.

The quickest solution would simply be to use a raycast from the center of the screen and forward, and set the object to the minimum of the distance given by the scroll wheel, and the distance of the raycast:

void HoldObject([URL='http://unity3d.com/support/documentation/ScriptReference/30_search.html?q=GameObject']GameObject[/URL] heldObject) {

    float distanceToObstacle = maxDistance;
    RaycastHit hit;
    if(Physics.Raycast(mainCamera.transform.[URL='http://unity3d.com/support/documentation/ScriptReference/30_search.html?q=position']position[/URL], mainCamera.transform.[URL='http://unity3d.com/support/documentation/ScriptReference/30_search.html?q=forward']forward[/URL], out hit, maxDistance)) {
       distanceToObstacle = hit.distance;
    }

    distance = distance +[URL='http://unity3d.com/support/documentation/ScriptReference/30_search.html?q=Input']Input[/URL].[URL='http://unity3d.com/support/documentation/ScriptReference/30_search.html?q=GetAxis']GetAxis[/URL]("Mouse ScrollWheel");
    float actualMaxDistance = Mathf.Min(maxDistance, distanceToObstacle);
    if(distance > actualMaxDistance)
        distance = actualMaxDistance;
  
    //The rest as before

This isn’t a complete solution to the problem. In particular, your object will now clip halfway through whatever’s in front of your player. You’ll have to reduce the distanceToObstacle by an appropriate amount depending on what you’re carrying, but that should be easy enough to figure out. Half the size of the collider on the thing should be a good baseline.

It also might not compile, I didn’t check. Let’s call that “left as an exercise to the reader”. Also the raycast might hit the object you’re holding, so you’ll have to take care of that somehow.