示例#1
0
    void GrabObject()
    {
        Vector3 middlePoint = this.transform.position;

        // Iterate the grabbable objects, find the closest one in range and start to grab it.
        foreach (GrabbaleObject obj in GrabbaleObject.instances)
        {
            if (Vector3.Distance(middlePoint, obj.transform.position) < interactionDistanceThreshold && previousFingerDist > grabEnableThreshold)
            {
                reachableObject = obj;
                if (grabbedObject == null)
                {
                    reachableObject.OnGetInReach.Invoke();
                    if (currentFingerDist < grabStartThreshold)
                    {
                        grabbedObject = obj;
                        grabbedObject.OnGrab.Invoke();
                        grabbedObjectParent                   = grabbedObject.transform.parent;
                        grabbedObject.transform.parent        = this.transform;
                        grabbedObject.transform.localPosition = Vector3.zero;
                        break;
                    }
                }
            }
            else
            {
                if (grabbedObject != null)
                {
                    if (currentFingerDist > grabEndThreshold)
                    {
                        grabbedObject.transform.parent = grabbedObjectParent;
                        grabbedObject.OnRelease.Invoke();
                        grabbedObject.OnThrow.Invoke(this.speed);
                        grabbedObject = null;
                    }
                }
                else
                {
                    if (reachableObject == obj)
                    {
                        reachableObject.OnOutOfReach.Invoke();
                        reachableObject = null;
                    }
                }
            }
        }
    }
    void UpdateGrabState()
    {
        GestureName currentGesture = hand.GetGestureName();

        bool isClosingFingers = (bendingAngularSpeed > anguarSpeedThresh);
        bool isOpeningFingers = (bendingAngularSpeed < -anguarSpeedThresh);

        if (activeObject != null && activeObject.IsAvailableForGrab() == false &&
            grabState != GrabState.ObjectInHold) // grabbed by the other hand
        {
            activeObject = null;
            grabState    = GrabState.ObjectOutOfReach;
        }

        if ((grabState == GrabState.ObjectOutOfReach) ||
            (grabState == GrabState.ObjectInReach && !isClosingFingers) ||
            (grabState == GrabState.ObjectReleased))
        {
            // Iterate all grabbable objects, find the closest available one.
            GrabbaleObject closestAvailableObj = null;
            float          minDistance         = 1000f;
            foreach (GrabbaleObject obj in GrabbaleObject.instances)
            {
                if (obj.IsAvailableForGrab())
                {
                    float distance = Vector3.Distance(this.transform.position, obj.transform.position);
                    if (distance < minDistance)
                    {
                        minDistance         = distance;
                        closestAvailableObj = obj;
                    }
                }
            }

            // Mark the closest available object as active
            activeObject = closestAvailableObj;

            // Check if it is range.
            bool inReach = (minDistance < grabEnableDistance);

            if (activeObject != null && (currentGesture == GestureName.Grab || currentGesture == GestureName.Palm ||
                                         currentBendingAngle < grabEnableAngle))
            {
                // To give user visual feedbacks, update the outline color on the active object
                // based on its current distance to the hand.
                activeObject.UpdateOutlineColorBasedOnDistance(minDistance);

                // Reset the outline color (fully transparent) on the last active object if it was different
                if (prevActiveObject != null && prevActiveObject != activeObject)
                {
                    prevActiveObject.SetOutlineColorTransparency(0);
                }

                // If we are close enough to grab the currently active object
                if (inReach && (grabState != GrabState.ObjectInReach || activeObject != prevActiveObject))
                {
                    activeObject.OnGetInReach.Invoke();
                    grabState = GrabState.ObjectInReach;
                }
            }

            // Note, we want to ignore movement (which can cause ObjectInReach state to change to ObjectOutOfReach)
            // if user is already in the middle of grabbing the object
            if (!inReach && !(grabState == GrabState.ObjectInReach && isClosingFingers))
            {
                if (grabState != GrabState.ObjectOutOfReach || activeObject != prevActiveObject)
                {
                    if (activeObject != null)
                    {
                        activeObject.OnOutOfReach.Invoke();
                    }

                    grabState = GrabState.ObjectOutOfReach;
                }
            }
        }

        if (grabState == GrabState.ObjectInReach)
        {
            if ((currentBendingAngle > grabStartAngle || currentGesture == GestureName.Fist) && isClosingFingers)
            {
                // To give user visual feedbacks, make the hand transparent.
                if (meshHandRenderMgr != null)
                {
                    meshHandRenderMgr.DisableHandOutline();
                    meshHandRenderMgr.FadeOut();
                }

                if (activeObject != null)
                {
                    activeObject.OnGrab.Invoke();
                    // Save the parent transform
                    grabbedObjectParent                  = activeObject.transform.parent;
                    activeObject.transform.parent        = this.transform;
                    activeObject.transform.localPosition = Vector3.zero;
                    // Disable the object for grab
                    activeObject.SetAvailableForGrab(false);
                }
                grabState = GrabState.ObjectInHold;
            }
        }

        if (grabState == GrabState.ObjectInHold)
        {
            if (currentBendingAngle < grabEndAngle && isOpeningFingers)
            {
                // To give user visual feedbacks, make the hand opaque (default).
                if (meshHandRenderMgr != null)
                {
                    meshHandRenderMgr.FadeIn();
                }

                if (activeObject != null)
                {
                    activeObject.OnRelease.Invoke();

                    Vector3 velocity = (velocityCalculator != null) ? velocityCalculator.CalculateVelocity() : Vector3.zero;
                    if (Vector3.Magnitude(velocity) > 0)
                    {
                        activeObject.OnThrow.Invoke(velocity);
                        // Enable the object for grab later
                        activeObject.SetAvailableForGrab(true, activeObject.FlyBackTime());
                    }
                    else
                    {
                        // Enable the object for grab right away
                        activeObject.SetAvailableForGrab(true, 0);
                    }
                    // Restore the parent transform
                    activeObject.transform.parent = grabbedObjectParent;
                }

                grabState = GrabState.ObjectReleased;
            }
        }

        //Debug.Log("Grab state = " + grabState);


        // To give user visual feedbacks, highlight hand outline if it is hovering an object, otherwise disable outline.
        bool isHovering = (grabState == GrabState.ObjectInReach);

        if (meshHandRenderMgr != null)
        {
            if (isHovering && !isHoveringLastFrame)
            {
                meshHandRenderMgr.EnableHandOutline();
            }
            else if (!isHovering && isHoveringLastFrame)
            {
                meshHandRenderMgr.DisableHandOutline();
            }
        }
        isHoveringLastFrame = isHovering;

        prevActiveObject = activeObject;
    }