Search Unity

GameObjects Has Spasms When Picked Up

Discussion in 'Scripting' started by SeanGause, Oct 21, 2017.

  1. SeanGause

    SeanGause

    Joined:
    Dec 24, 2015
    Posts:
    127
    So I made a script so that I would be able to pick up cubes in my first-person game. The picking up part works fine, but if you push the cube against a wall or the floor (or any surface) after you have picked it up, it shakes violently and spasms. Is there a way to fix this? Here's the script:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class UseManager : MonoBehaviour
    6. {
    7.     public GameObject cube;
    8.     RaycastHit hit;
    9.  
    10.     public GameObject cubeHolder;
    11.     public Transform cubeHolderTransform;
    12.     public FixedJoint joint;
    13.  
    14.     public bool isHolding = false;
    15.  
    16.     public void dropCube()
    17.     {
    18.         Destroy(cube.GetComponent<FixedJoint>());
    19.         cube.transform.parent = null;
    20.         cube.GetComponent<Rigidbody>().useGravity = true;
    21.         //cube.transform.localRotation = transform.rotation;
    22.         isHolding = false;
    23.         StartCoroutine(wait1());
    24.         Debug.Log("Cube dropped");
    25.     }
    26.     IEnumerator wait1()
    27.     {
    28.         yield return new WaitForSeconds(0.5f);
    29.     }
    30.  
    31.     void Update()
    32.     {
    33.         if (Input.GetMouseButtonDown(0))
    34.         {
    35.             if (Physics.Raycast(transform.position, transform.forward, out hit, 3f))
    36.             {
    37.                 //Cube pickup script
    38.                 if ((hit.transform.tag == "cube" || hit.transform.tag == "cubeBlue" || hit.transform.tag == "cubeYellow") && isHolding == false)
    39.                 {
    40.                     cube = hit.transform.gameObject;
    41.                     cube.transform.position = cubeHolder.transform.position;
    42.                     //cube.transform.localRotation = transform.rotation;
    43.                     //cube.transform.SetParent(cubeHolderTransform);
    44.                     //cube.GetComponent<Rigidbody>().useGravity = false;
    45.                     joint = cube.gameObject.AddComponent<FixedJoint>();
    46.                     joint.breakForce = 300000;
    47.                     joint.connectedBody = cubeHolder.GetComponent<Rigidbody>();
    48.                     isHolding = true;
    49.                     StartCoroutine(wait1());
    50.                 }
    51.                 else if (isHolding == true)
    52.                 {
    53.                     dropCube();
    54.                 }
    55.             }
    56.         }
    57.     }
    58. }
     
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    None of this code shows how you move the cube after you've picked it up. Are you moving the holding object with something like transform.position rather than using physics?
     
  3. SeanGause

    SeanGause

    Joined:
    Dec 24, 2015
    Posts:
    127
    The code forms a fixed joint between the cube and a gameObject, cubeHolder, which is parented to my FPScontrollers camera.
     
  4. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    So you're just manipulating your FPSController camera's transform directly, which is basically teleportation to the physics engine. You'll need to use proper physics manipulations to get smooth results. Right now, it's basically teleporting your cube inside the wall every frame and then the physics engine goes "that's not right" and tries to fix it.
     
  5. SeanGause

    SeanGause

    Joined:
    Dec 24, 2015
    Posts:
    127
    How would I use "proper physics manipulations"? I'm not well versed in this area. Would I be able to just change the script? If so, what would I change?
     
  6. Grizmu

    Grizmu

    Joined:
    Aug 27, 2013
    Posts:
    131
    If you use a joint, it can, and will, cause jittery movement on objects attached by it, when they are interacting with other physical objects, where either of them are moved by setting their position directly. To avoid jittery movement of the joint attached objects you can either:
    1. Simply not use the joint. Attach the cube to cubeHolder with SetParent.
    2. Disable the picked up cube's collider, and enable it when you drop it.
    3. Move the cubeHolder using only AddForce/AddTorque methods of its Rigidbody. Setting the velocity directly might also work for some conditions.
    Options 1 and 2 will cause render clipping, as now the picked up cube goes through other objects. To avoid it, you can add a new render layer, add a second camera and render the character first person view with this second camera, on top of what your main camera renders. This will make the cube appear always in front of everything else.
     
  7. SeanGause

    SeanGause

    Joined:
    Dec 24, 2015
    Posts:
    127
    That would work, and I tried number 1 and number 2. The cube is then able to be dropped through a wall, which is why I switched to a joint.
     
  8. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    Just sanity-check for the edge cases- no reason to switch to a bizarre control scheme because of that IMO.

    In this case, an example sanity-check could just be raycasting directly ahead of the character for obstacles when "drop" is pressed (or the character's waist or knees even, maybe, if you want better accuracy). If an obstacle is hit within the range to cause problems with the drop, get the distance to impact, then send that distance to the drop function and offset the exact drop position back toward the character from the impact position by half of the box width.

    In other words, "wall is 1.2 feet ahead of character, will obstruct drop placement- place box 1.2 feet minus (half box width) distance ahead instead of normal location, so it doesn't intersect/fall through the wall". Just an example.