Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

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

Discussion in 'Scripting' started by nostalgicbear, Dec 4, 2015.

  1. nostalgicbear

    nostalgicbear

    Joined:
    Mar 21, 2013
    Posts:
    98
    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.

    Code (CSharp):
    1. void HoldObject(GameObject heldObject)
    2.     {
    3.         distance = distance + Input.GetAxis ("Mouse ScrollWheel"); //float distance refers to how far away the object is away from the player
    4.  
    5.         if (distance > maxDistance) { //This prevents the player from constantly scrolling the wheel to move the object really far away
    6.             distance = maxDistance;
    7.         }
    8.        
    9.         if (distance < minDistance) { //This prevents the player from constantly scrolling the wheel to move the object back through the players body
    10.             distance = minDistance;
    11.         }
    12.  
    13. /*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.
    14. */
    15.  
    16.         heldObject.transform.position = Vector3.Lerp (heldObject.transform.position, mainCamera.transform.position + mainCamera.transform.forward * distance, Time.deltaTime * smooth);
    17.  
    18.         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.
    19.             heldObject.transform.rotation = Quaternion.identity;
    20.         } else {
    21.             heldObject.transform.Rotate(Vector3.up * Time.deltaTime * 300); //Else you must be holding right click, so rotate the held object
    22.         }
    23.     }
     
  2. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    906
    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.
     
  3. nostalgicbear

    nostalgicbear

    Joined:
    Mar 21, 2013
    Posts:
    98
    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 :

    Code (CSharp):
    1. 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
     
  4. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    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
     
    ThermalFusion likes this.
  5. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    906
    Yes, because that is the same thing you are doing. Just that youre passing through a lot of components getting to the same Transform.
     
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,199
    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:

    Code (CSharp):
    1. void HoldObject([URL='http://unity3d.com/support/documentation/ScriptReference/30_search.html?q=GameObject']GameObject[/URL] heldObject) {
    2.  
    3.     float distanceToObstacle = maxDistance;
    4.     RaycastHit hit;
    5.     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)) {
    6.        distanceToObstacle = hit.distance;
    7.     }
    8.  
    9.     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");
    10.     float actualMaxDistance = Mathf.Min(maxDistance, distanceToObstacle);
    11.     if(distance > actualMaxDistance)
    12.         distance = actualMaxDistance;
    13.  
    14.     //The rest as before
    15.  
    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.