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

Oculus Distance Grabber script not parenting correctly

Discussion in 'Scripting' started by Starmind01, Feb 15, 2020.

  1. Starmind01

    Starmind01

    Joined:
    May 23, 2019
    Posts:
    78
    I have been working on getting things to mount correctly when grabbed. With the current Oculus Integration package, the distance grabber has some movement to the gameobject that is parented to the hands. In some games that i have played to fix that small problem, people have just made the hand go invisible when grabbing and only the grabbed object remains visible. So, I made a script to parent the grabbed object to the hand to remove the wobble. From what I can see it is caused by the linear motion when using the left thumbstick. I did try to remove the linear motion from the grabbed object, but it continued. Even freezing all constraints did not work.

    My question for those of you that do more coding than I do, How do we remove the wobble?

    Here is the Distance Grabber script:
    Code (CSharp):
    1. /************************************************************************************
    2.  
    3. Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
    4.  
    5. See SampleFramework license.txt for license terms.  Unless required by applicable law
    6. or agreed to in writing, the sample code is provided “AS IS” WITHOUT WARRANTIES OR
    7. CONDITIONS OF ANY KIND, either express or implied.  See the license for specific
    8. language governing permissions and limitations under the license.
    9.  
    10. ************************************************************************************/
    11.  
    12. using System.Collections.Generic;
    13. using UnityEngine;
    14. #if UNITY_EDITOR
    15. using UnityEngine.SceneManagement;
    16. #endif
    17.  
    18.  
    19.  
    20. namespace OculusSampleFramework
    21. {
    22.     /// <summary>
    23.     /// Allows grabbing and throwing of objects with the DistanceGrabbable component on them.
    24.     /// </summary>
    25.     [RequireComponent(typeof(Rigidbody))]
    26.     public class DistanceGrabber : OVRGrabber
    27.     {
    28.  
    29.         // Radius of sphere used in spherecast from hand along forward ray to find target object.
    30.         [SerializeField]
    31.         public Color m_focusColor;
    32.  
    33.         // Radius of sphere used in spherecast from hand along forward ray to find target object.
    34.         [SerializeField]
    35.         float m_spherecastRadius = 0;
    36.  
    37.         // Distance below which no-snap objects won't be teleported, but will instead be left
    38.         // where they are in relation to the hand.
    39.         [SerializeField]
    40.         float m_noSnapThreshhold = 0.05f;
    41.  
    42.         [SerializeField]
    43.         bool m_useSpherecast;
    44.         public bool UseSpherecast
    45.         {
    46.             get { return m_useSpherecast; }
    47.             set
    48.             {
    49.                 m_useSpherecast = value;
    50.                 GrabVolumeEnable(!m_useSpherecast);
    51.             }
    52.         }
    53.  
    54.         // Public to allow changing in demo.
    55.         [SerializeField]
    56.         public bool m_preventGrabThroughWalls;
    57.  
    58.         [SerializeField]
    59.         float m_objectPullVelocity = 10.0f;
    60.         float m_objectPullMaxRotationRate = 360.0f; // max rotation rate in degrees per second
    61.  
    62.         bool m_movingObjectToHand = false;
    63.  
    64.         // Objects can be distance grabbed up to this distance from the hand.
    65.         [SerializeField]
    66.         float m_maxGrabDistance;
    67.  
    68.         // Only allow grabbing objects in this layer.
    69.         // NOTE: you can use the value -1 to attempt to grab everything.
    70.         [SerializeField]
    71.         int m_grabObjectsInLayer = 0;
    72.         [SerializeField]
    73.         int m_obstructionLayer = 0;
    74.  
    75.         DistanceGrabber m_otherHand;
    76.  
    77.         protected DistanceGrabbable m_target;
    78.         // Tracked separately from m_target, because we support child colliders of a DistanceGrabbable.
    79.         protected Collider m_targetCollider;
    80.  
    81.         protected override void Start()
    82.         {
    83.             base.Start();
    84.  
    85.             // Set up our max grab distance to be based on the player's max grab distance.
    86.             // Adding a liberal margin of error here, because users can move away some from the
    87.             // OVRPlayerController, and also players have arms.
    88.             // Note that there's no major downside to making this value too high, as objects
    89.             // outside the player's grabbable trigger volume will not be eligible targets regardless.
    90.             SphereCollider sc = m_player.GetComponentInChildren<SphereCollider>();
    91.             m_maxGrabDistance = sc.radius + 3.0f;
    92.  
    93.             if(m_parentHeldObject == true)
    94.             {
    95.                 Debug.LogError("m_parentHeldObject incompatible with DistanceGrabber. Setting to false.");
    96.                 m_parentHeldObject = false;
    97.             }
    98.  
    99.             DistanceGrabber[] grabbers = FindObjectsOfType<DistanceGrabber>();
    100.             for (int i = 0; i < grabbers.Length; ++i)
    101.             {
    102.                 if (grabbers[i] != this) m_otherHand = grabbers[i];
    103.             }
    104.             Debug.Assert(m_otherHand != null);
    105.  
    106. #if UNITY_EDITOR
    107.             OVRPlugin.SendEvent("distance_grabber", (SceneManager.GetActiveScene().name == "DistanceGrab").ToString(), "sample_framework");
    108. #endif
    109.     }
    110.  
    111.         public override void Update()
    112.         {
    113.             base.Update();
    114.  
    115.             Debug.DrawRay(transform.position, transform.forward, Color.red, 0.1f);
    116.            
    117.             DistanceGrabbable target;
    118.             Collider targetColl;
    119.             FindTarget(out target, out targetColl);
    120.  
    121.             if (target != m_target)
    122.             {
    123.                 if (m_target != null)
    124.                 {
    125.                     m_target.Targeted = m_otherHand.m_target == m_target;
    126.                 }
    127.                 if(m_target != null)
    128.                     m_target.ClearColor();
    129.                 if(target != null)
    130.                     target.SetColor(m_focusColor);
    131.                 m_target = target;
    132.                 m_targetCollider = targetColl;
    133.                 if (m_target != null)
    134.                 {
    135.                     m_target.Targeted = true;
    136.                 }
    137.             }
    138.         }
    139.  
    140.         protected override void GrabBegin()
    141.         {
    142.             DistanceGrabbable closestGrabbable = m_target;
    143.             Collider closestGrabbableCollider = m_targetCollider;
    144.  
    145.             GrabVolumeEnable(false);
    146.  
    147.             if (closestGrabbable != null)
    148.             {
    149.                 if (closestGrabbable.isGrabbed)
    150.                 {
    151.                     ((DistanceGrabber)closestGrabbable.grabbedBy).OffhandGrabbed(closestGrabbable);
    152.                 }
    153.  
    154.                 m_grabbedObj = closestGrabbable;
    155.                 m_grabbedObj.GrabBegin(this, closestGrabbableCollider);
    156.                 SetPlayerIgnoreCollision(m_grabbedObj.gameObject, true);
    157.  
    158.                 m_movingObjectToHand = true;
    159.                 m_lastPos = transform.position;
    160.                 m_lastRot = transform.rotation;
    161.  
    162.                 // If it's within a certain distance respect the no-snap.
    163.                 Vector3 closestPointOnBounds = closestGrabbableCollider.ClosestPointOnBounds(m_gripTransform.position);
    164.                 if(!m_grabbedObj.snapPosition && !m_grabbedObj.snapOrientation && m_noSnapThreshhold > 0.0f && (closestPointOnBounds - m_gripTransform.position).magnitude < m_noSnapThreshhold)
    165.                 {
    166.                     Vector3 relPos = m_grabbedObj.transform.position - transform.position;
    167.                     m_movingObjectToHand = false;
    168.                     relPos = Quaternion.Inverse(transform.rotation) * relPos;
    169.                     m_grabbedObjectPosOff = relPos;
    170.                     Quaternion relOri = Quaternion.Inverse(transform.rotation) * m_grabbedObj.transform.rotation;
    171.                     m_grabbedObjectRotOff = relOri;
    172.                 }
    173.                 else
    174.                 {
    175.                     // Set up offsets for grabbed object desired position relative to hand.
    176.                     m_grabbedObjectPosOff = m_gripTransform.localPosition;
    177.                     if (m_grabbedObj.snapOffset)
    178.                     {
    179.                         Vector3 snapOffset = m_grabbedObj.snapOffset.position;
    180.                         if (m_controller == OVRInput.Controller.LTouch) snapOffset.x = -snapOffset.x;
    181.                         m_grabbedObjectPosOff += snapOffset;
    182.                     }
    183.  
    184.                     m_grabbedObjectRotOff = m_gripTransform.localRotation;
    185.                     if (m_grabbedObj.snapOffset)
    186.                     {
    187.                         m_grabbedObjectRotOff = m_grabbedObj.snapOffset.rotation * m_grabbedObjectRotOff;
    188.                     }
    189.                 }
    190.  
    191.             }
    192.         }
    193.  
    194.         protected override void MoveGrabbedObject(Vector3 pos, Quaternion rot, bool forceTeleport = false)
    195.         {
    196.             if (m_grabbedObj == null)
    197.             {
    198.                 return;
    199.             }
    200.  
    201.             Rigidbody grabbedRigidbody = m_grabbedObj.grabbedRigidbody;
    202.             Vector3 grabbablePosition = pos + rot * m_grabbedObjectPosOff;
    203.             Quaternion grabbableRotation = rot * m_grabbedObjectRotOff;
    204.  
    205.             if (m_movingObjectToHand)
    206.             {
    207.                 float travel = m_objectPullVelocity * Time.deltaTime;
    208.                 Vector3 dir = grabbablePosition - m_grabbedObj.transform.position;
    209.                 if(travel * travel * 1.1f > dir.sqrMagnitude)
    210.                 {
    211.                     m_movingObjectToHand = false;
    212.                 }
    213.                 else
    214.                 {
    215.                     dir.Normalize();
    216.                     grabbablePosition = m_grabbedObj.transform.position + dir * travel;
    217.                     grabbableRotation = Quaternion.RotateTowards(m_grabbedObj.transform.rotation, grabbableRotation, m_objectPullMaxRotationRate * Time.deltaTime);
    218.                 }
    219.             }
    220.             grabbedRigidbody.MovePosition(grabbablePosition);
    221.             grabbedRigidbody.MoveRotation(grabbableRotation);
    222.         }
    223.  
    224.         static private DistanceGrabbable HitInfoToGrabbable(RaycastHit hitInfo)
    225.         {
    226.             if (hitInfo.collider != null)
    227.             {
    228.                 GameObject go = hitInfo.collider.gameObject;
    229.                 return go.GetComponent<DistanceGrabbable>() ?? go.GetComponentInParent<DistanceGrabbable>();
    230.             }
    231.             return null;
    232.         }
    233.  
    234.         protected bool FindTarget(out DistanceGrabbable dgOut, out Collider collOut)
    235.         {
    236.             dgOut = null;
    237.             collOut = null;
    238.             float closestMagSq = float.MaxValue;
    239.  
    240.             // First test for objects within the grab volume, if we're using those.
    241.             // (Some usage of DistanceGrabber will not use grab volumes, and will only
    242.             // use spherecasts, and that's supported.)
    243.             foreach (OVRGrabbable cg in m_grabCandidates.Keys)
    244.             {
    245.                 DistanceGrabbable grabbable = cg as DistanceGrabbable;
    246.                 bool canGrab = grabbable != null && grabbable.InRange && !(grabbable.isGrabbed && !grabbable.allowOffhandGrab);
    247.                 if (canGrab && m_grabObjectsInLayer >= 0) canGrab = grabbable.gameObject.layer == m_grabObjectsInLayer;
    248.                 if (!canGrab)
    249.                 {
    250.                     continue;
    251.                 }
    252.  
    253.                 for (int j = 0; j < grabbable.grabPoints.Length; ++j)
    254.                 {
    255.                     Collider grabbableCollider = grabbable.grabPoints[j];
    256.                     // Store the closest grabbable
    257.                     Vector3 closestPointOnBounds = grabbableCollider.ClosestPointOnBounds(m_gripTransform.position);
    258.                     float grabbableMagSq = (m_gripTransform.position - closestPointOnBounds).sqrMagnitude;
    259.                     if (grabbableMagSq < closestMagSq)
    260.                     {
    261.                         bool accept = true;
    262.                         if(m_preventGrabThroughWalls)
    263.                         {
    264.                             // NOTE: if this raycast fails, ideally we'd try other rays near the edges of the object, especially for large objects.
    265.                             // NOTE 2: todo optimization: sort the objects before performing any raycasts.
    266.                             Ray ray = new Ray();
    267.                             ray.direction = grabbable.transform.position - m_gripTransform.position;
    268.                             ray.origin = m_gripTransform.position;
    269.                             RaycastHit obstructionHitInfo;
    270.                             Debug.DrawRay(ray.origin, ray.direction, Color.red, 0.1f);
    271.  
    272.                             if (Physics.Raycast(ray, out obstructionHitInfo, m_maxGrabDistance, 1 << m_obstructionLayer))
    273.                             {
    274.                                 float distToObject = (grabbableCollider.ClosestPointOnBounds(m_gripTransform.position) - m_gripTransform.position).magnitude;
    275.                                 if(distToObject > obstructionHitInfo.distance * 1.1)
    276.                                 {
    277.                                     accept = false;
    278.                                 }
    279.                             }
    280.                         }
    281.                         if(accept)
    282.                         {
    283.                             closestMagSq = grabbableMagSq;
    284.                             dgOut = grabbable;
    285.                             collOut = grabbableCollider;
    286.                         }
    287.                     }
    288.                 }
    289.             }
    290.  
    291.             if (dgOut == null && m_useSpherecast)
    292.             {
    293.                 return FindTargetWithSpherecast(out dgOut, out collOut);
    294.             }
    295.             return dgOut != null;
    296.         }
    297.  
    298.         protected bool FindTargetWithSpherecast(out DistanceGrabbable dgOut, out Collider collOut)
    299.         {
    300.             dgOut = null;
    301.             collOut = null;
    302.             Ray ray = new Ray(m_gripTransform.position, m_gripTransform.forward);
    303.             RaycastHit hitInfo;
    304.  
    305.             // If no objects in grab volume, raycast.
    306.             // Potential optimization:
    307.             // In DistanceGrabbable.RefreshCrosshairs, we could move the object between collision layers.
    308.             // If it's in range, it would move into the layer DistanceGrabber.m_grabObjectsInLayer,
    309.             // and if out of range, into another layer so it's ignored by DistanceGrabber's SphereCast.
    310.             // However, we're limiting the SphereCast by m_maxGrabDistance, so the optimization doesn't seem
    311.             // essential.
    312.             int layer = (m_grabObjectsInLayer == -1) ? ~0 : 1 << m_grabObjectsInLayer;
    313.             if (Physics.SphereCast(ray, m_spherecastRadius, out hitInfo, m_maxGrabDistance, layer))
    314.             {
    315.                 DistanceGrabbable grabbable = null;
    316.                 Collider hitCollider = null;
    317.                 if (hitInfo.collider != null)
    318.                 {
    319.                     grabbable = hitInfo.collider.gameObject.GetComponentInParent<DistanceGrabbable>();
    320.                     hitCollider = grabbable == null ? null : hitInfo.collider;
    321.                     if(grabbable)
    322.                     {
    323.                         dgOut = grabbable;
    324.                         collOut = hitCollider;
    325.                     }
    326.                 }
    327.  
    328.                 if (grabbable != null && m_preventGrabThroughWalls)
    329.                 {
    330.                     // Found a valid hit. Now test to see if it's blocked by collision.
    331.                     RaycastHit obstructionHitInfo;
    332.                     ray.direction = hitInfo.point - m_gripTransform.position;
    333.  
    334.                     dgOut = grabbable;
    335.                     collOut = hitCollider;
    336.                     if (Physics.Raycast(ray, out obstructionHitInfo, 1 << m_obstructionLayer))
    337.                     {
    338.                         DistanceGrabbable obstruction = null;
    339.                         if(hitInfo.collider != null)
    340.                         {
    341.                             obstruction = obstructionHitInfo.collider.gameObject.GetComponentInParent<DistanceGrabbable>();
    342.                         }
    343.                         if (obstruction != grabbable && obstructionHitInfo.distance < hitInfo.distance)
    344.                         {
    345.                             dgOut = null;
    346.                             collOut = null;
    347.                         }
    348.                     }
    349.                 }
    350.             }
    351.             return dgOut != null;
    352.         }
    353.  
    354.         protected override void GrabVolumeEnable(bool enabled)
    355.         {
    356.             if(m_useSpherecast) enabled = false;
    357.             base.GrabVolumeEnable(enabled);
    358.         }
    359.  
    360.         // Just here to allow calling of a protected member function.
    361.       protected override void OffhandGrabbed(OVRGrabbable grabbable)
    362.         {
    363.             base.OffhandGrabbed(grabbable);
    364.         }
    365.     }
    366. }
    367.  

    And here is my quick fix script:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class GrabbedObject : MonoBehaviour
    6. {
    7.     private bool grabbed;
    8.     public bool hasOffset;
    9.  
    10.     private void Update()
    11.     {
    12.         grabbed = GetComponent<OVRGrabbable>().isGrabbed;
    13.         if (grabbed == true)
    14.         {
    15.             if(hasOffset == true)
    16.             {
    17.                 transform.SetParent(GetComponent<OVRGrabbable>().snapOffset.transform);
    18.                 transform.position = transform.parent.position;
    19.             }
    20.             if(hasOffset == false)
    21.             {
    22.                 transform.SetParent(GetComponent<OVRGrabbable>().grabbedBy.transform);
    23.                 transform.position = transform.parent.position;
    24.             }
    25.         }
    26.         if (grabbed == false)
    27.         {
    28.             gameObject.transform.parent = null;
    29.         }
    30.     }
    31. }
    Here is a small video of the wobble.
     
  2. ChunkyToads

    ChunkyToads

    Joined:
    Jun 21, 2017
    Posts:
    8
    UPDATE: Hours in... solved this issue made a few adjustments to the code you posted in Unity forum. Thanks for getting the ball rolling on this btw. Anyways, changes are as follows, after which in the Unity inspector you must set 'gripTrans' in the open slot. Note, even though code no longer references a snapoffset, I am using one which is setup in scene ahead of time and referenced in the DistanceGrabber component. Also object rotation may be off, when grabbed even if now moving correctly. To fix this, simply rotate and position the gripTrans in scene while holding object (you can place near perfectly in hand). If you need more details msg me. I hope this helps if you have not resolved the issue entirely yet :)

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

    public class GrabbedObject : MonoBehaviour
    {
    private bool grabbed;

    //public slot for you to place gripTrans via inspector
    public GameObject thing;

    private void Update()
    { grabbed = GetComponent<OVRGrabbable>().isGrabbed;
    if (grabbed == true)
    {

    //sets transform of grabbed object to chosen parents rotation & position transform.SetParent(thing.transform) ;
    transform.position = transform.parent.position;
    transform.rotation = transform.parent.rotation;
    }

    if (grabbed == false)
    {
    gameObject.transform.parent = null;
    }
    }
    }
     
    Starmind01 likes this.
  3. Starmind01

    Starmind01

    Joined:
    May 23, 2019
    Posts:
    78
    Sorry, I have not done anything more with this issue due to not actually doing anything with code since I made the post. Thank you for the fix! I am sure those of us with the same issue will get a great benefit from your hard work.
    Again, thank you!