Search Unity

Resolved Stop player from dropping objects through walls?

Discussion in 'Scripting' started by jlorenzi, May 7, 2022.

  1. jlorenzi

    jlorenzi

    Joined:
    May 2, 2021
    Posts:
    293
    I made a simple script that lets the player pick up and throw objects. The problem is that if the player walks close to a wall, the object will go outside of the wall and the player can throw it to get it outside of the map. When I tried changing rigidbody.useGravity to false instead of setting rigidbody.isKinematic to true it did stop the object from going through walls, but as soon as it hit a wall it would bounce off it and float away.
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3.  
    4. public class PickUpObjects : MonoBehaviour
    5. {
    6.     public Transform grabPoint;
    7.     public Text buttomPrompt;
    8.  
    9.     private float waitTimeBeforeThrow = -0.4f;
    10.     private float waitTimeBeforeGrab = -0.4f;
    11.     private bool inPickUpRange;
    12.     private bool pickedUp;
    13.     private Transform objectToPickUp;
    14.  
    15.     private void OnTriggerStay(Collider other)
    16.     {
    17.         if (other.CompareTag("Grabbable Object"))
    18.         {
    19.             if (pickedUp)
    20.             {
    21.                 return;
    22.             }
    23.  
    24.             inPickUpRange = true;
    25.  
    26.             buttomPrompt.text = "E - Pick up";
    27.  
    28.             objectToPickUp = other.transform;
    29.         }
    30.     }
    31.    
    32.     private void OnTriggerExit(Collider other)
    33.     {
    34.         inPickUpRange = false;
    35.  
    36.         buttomPrompt.text = "";
    37.     }
    38.  
    39.     void Update()
    40.     {
    41.         if (inPickUpRange)
    42.         {
    43.             waitTimeBeforeGrab += Time.deltaTime;
    44.  
    45.             if (waitTimeBeforeGrab > 0)
    46.             {
    47.                 if (Input.GetKeyDown(KeyCode.E))
    48.                 {
    49.                     PickUp(objectToPickUp);
    50.                 }
    51.             }
    52.         }
    53.  
    54.         if (pickedUp)
    55.         {
    56.             waitTimeBeforeThrow += Time.deltaTime;
    57.  
    58.             if (waitTimeBeforeThrow > 0)
    59.             {
    60.                 if (Input.GetKey(KeyCode.E))
    61.                 {
    62.                     Throw(objectToPickUp.GetComponent<Rigidbody>(), 7);
    63.                 }
    64.             }
    65.         }
    66.     }
    67.  
    68.     void PickUp(Transform grab)
    69.     {
    70.         buttomPrompt.text = "";
    71.  
    72.         pickedUp = true;
    73.  
    74.         grab.GetComponent<Rigidbody>().isKinematic = true;
    75.  
    76.         waitTimeBeforeGrab = -0.4f;
    77.  
    78.         grab.parent = transform.parent;
    79.  
    80.         grab.position = grabPoint.position;
    81.         grab.rotation = Quaternion.identity;
    82.         grab.localRotation = Quaternion.identity;
    83.     }
    84.  
    85.     void Throw(Rigidbody rb, float throwValue)
    86.     {
    87.         waitTimeBeforeThrow = -0.4f;
    88.  
    89.         rb.transform.parent = null;
    90.  
    91.         rb.isKinematic = false;
    92.  
    93.         pickedUp = false;
    94.  
    95.         rb.AddForce(Camera.main.transform.forward * throwValue, ForceMode.Impulse);
    96.     }
    97. }
    98.  
     
  2. Adrian

    Adrian

    Joined:
    Apr 5, 2008
    Posts:
    1,066
    There's no easy solution to this problem. A more elegant and complicated solution would be to check if the pickup is colliding with walls (either using physics queries or making the pickup a kinematic trigger) and make it avoid them, so it never intersects a wall in the first place. This also makes it visually not clip into the wall and avoids it dropping on the other side but how exactly you would achieve this really depends on how your player is set up in your game.

    A simpler fix is to cast a ray before dropping the pickup from inside the player's collider to the center of the pickup and check if the ray hits any walls. If it does, then disable dropping or first move the pickup so that it doesn't intersect the wall using physics queries.
     
    Kurt-Dekker likes this.