Example #1
0
 /// <summary>Function for controller trigger fully pressed</summary>
 public void Grab()
 {
     if (!grabbing && !squeezing && holdingObj == null)
     {
         RaycastHit closestHit;
         if (HandClosestHit(out closestHit, reachDistance, LayerMask.GetMask("Grabbable", "Grabbing", "Holding", "Releasing")) != Vector3.zero)
         {
             StartCoroutine(GrabObject(closestHit));
         }
     }
     else if (holdingObj != null)
     {
         if (holdingObj.GetComponent <GrabLock>())
         {
             holdingObj.GetComponent <GrabLock>().OnGrabPressed?.Invoke();
         }
     }
 }
Example #2
0
        /// <summary>Takes a hit from a grabbable object and moves the hand towards that point, then calculates ideal hand shape</summary>
        IEnumerator GrabObject(RaycastHit hit)
        {
            Grabbable lookingAtGrab;

            if (GetGrabbable(lookingAtObj, out lookingAtGrab))
            {
                lookingAtGrab.Unhighlight();
            }

            lookingAtObj = null;

            Grabbable tempHoldingObj;

            if (!GetGrabbable(hit.collider.gameObject, out tempHoldingObj))
            {
                yield break;
            }

            //Checks if the grabbable script is enabled
            if (!tempHoldingObj.enabled)
            {
                yield break;
            }

            //If the hand doesn't match the settings
            if ((tempHoldingObj.handType == HandType.left && !left) || (tempHoldingObj.handType == HandType.right && left))
            {
                yield break;
            }

            //Hand Swap - One Handed Items
            if (tempHoldingObj.singleHandOnly && tempHoldingObj.HeldCount() > 0)
            {
                tempHoldingObj.ForceHandsRelease();
                yield return(new WaitForFixedUpdate());

                yield return(new WaitForEndOfFrame());
            }


            holdingObj   = tempHoldingObj;
            startGrabPos = transform.position;
            startGrabRot = transform.rotation;

            OnBeforeGrabbed?.Invoke(this, holdingObj);

            //GrabbableBase check - cancels grab if failed
            var grabBase = holdingObj.GetComponent <GrabbablePointBase>();

            if (grabBase != null && !grabBase.Align(this))
            {
                yield break;
            }


            //Set layers for grabbing
            var originalLayer = LayerMask.LayerToName(holdingObj.gameObject.layer);

            holdingObj.SetLayerRecursive(holdingObj.transform, LayerMask.NameToLayer("Grabbable"), LayerMask.NameToLayer("Grabbing"));
            holdingObj.SetLayerRecursive(holdingObj.transform, LayerMask.NameToLayer("Holding"), LayerMask.NameToLayer("Grabbing"));
            holdingObj.SetLayerRecursive(holdingObj.transform, LayerMask.NameToLayer("Releasing"), LayerMask.NameToLayer("Grabbing"));
            SetLayerRecursive(transform, LayerMask.NameToLayer("HandHolding"));

            //SETS GRAB POINT
            grabPoint          = new GameObject().transform;
            grabPoint.position = hit.point;
            grabPoint.parent   = hit.transform;

            grabbing        = true;
            palmOffset      = transform.position - palmTransform.position;
            moveTo.position = grabPoint.transform.position + palmOffset;
            moveTo.rotation = grabPoint.transform.rotation;
            freezeRot       = true;

            //Aligns the hand using the closest hit point
            IEnumerator AutoAllign()
            {
                foreach (var finger in fingers)
                {
                    finger.ResetBend();
                }

                var mass = body.mass;
                var dir  = HandClosestHit(out _, reachDistance, LayerMask.GetMask("Grabbing"));

                var palmOriginParent = palmTransform.parent;

                palmTransform.parent = null;
                var originParent = transform.parent;

                transform.parent = palmTransform;

                palmTransform.LookAt(grabPoint.position, transform.forward);

                transform.parent     = originParent;
                palmTransform.parent = palmOriginParent;
                body.mass            = 0;


                transform.position = grabPoint.position + palmOffset;

                grabbingFrame = true;
                body.WakeUp();
                holdingObj.body.WakeUp();
                Physics.SyncTransforms();

                yield return(new WaitForFixedUpdate());

                body.WakeUp();
                grabbingFrame = false;
                if (holdingObj != null)
                {
                    holdingObj.body.WakeUp();
                }
                body.mass = mass;
            }

            //Predetermined Pose
            if (holdingObj.GetComponent <GrabbablePose>())
            {
                grabPose = holdingObj.GetComponent <GrabbablePose>();
                grabPose.SetGrabPose(this);
            }

            //Allign Position
            else if (grabBase == null)
            {
                yield return(StartCoroutine(AutoAllign()));
            }

            if (holdingObj != null)
            {
                //Finger Bend
                if (grabPose == null)
                {
                    foreach (var finger in fingers)
                    {
                        finger.BendFingerUntilHit(fingerBendSteps, LayerMask.GetMask("Grabbing"));
                    }
                }


                //Connect Joints
                joint1 = gameObject.AddComponent <FixedJoint>();
                joint1.connectedBody = holdingObj.body;
                joint1.breakForce    = 10000000;
                joint1.breakTorque   = 10000000;

                joint1.connectedMassScale  = 1;
                joint1.massScale           = 1;
                joint1.enableCollision     = false;
                joint1.enablePreprocessing = false;

                joint2 = holdingObj.body.gameObject.AddComponent <FixedJoint>();
                joint2.connectedBody = body;
                joint2.breakForce    = 10000000;
                joint2.breakTorque   = 10000000;

                joint2.connectedMassScale  = 1;
                joint2.massScale           = 1;
                joint2.enableCollision     = false;
                joint2.enablePreprocessing = false;

                grabPoint.transform.position = transform.position;
                grabPoint.transform.rotation = transform.rotation;
                OnGrabbed?.Invoke(this, holdingObj);
                holdingObj.OnGrab(this);

                yield return(new WaitForFixedUpdate());

                if (holdingObj != null)
                {
                    joint1.breakForce  = holdingObj.jointBreakForce;
                    joint1.breakTorque = holdingObj.jointBreakForce;

                    joint2.breakForce  = holdingObj.jointBreakForce;
                    joint2.breakTorque = holdingObj.jointBreakForce;

                    grabLocked = true;
                }

                if (grabPose != null || grabBase != null)
                {
                    transform.rotation = moveTo.rotation;
                }
            }

            //Reset Values
            freezePos = false;
            freezeRot = false;
            grabbing  = false;

            yield return(new WaitForEndOfFrame());

            if (grabPose != null || grabBase != null)
            {
                transform.rotation = follow.rotation;
            }
        }