コード例 #1
0
    // Update is called once per frame
    void Update()
    {
        // Grab the current child input components
        InteractiveObject[] childInputs = transform.GetComponentsInChildren <InteractiveObject>();

        float             closestDist      = hoverDistance;
        Vector3           closestPoint     = new Vector3();
        Vector3           closestNormal    = new Vector3();
        Vector3           interactionPoint = new Vector3();
        Transform         closestBone      = null;
        InteractiveObject targetInput      = null;

        // Count up the active hands
        int       activeHands = 0;
        RigidHand activeHand  = null;

        foreach (var hand in hands)
        {
            if (hand.isActiveAndEnabled)
            {
                activeHands++;
                activeHand = hand;
            }
        }

        // We cycle through every finger-end collider in both hands and for all inputs to find the likely interaction target
        foreach (InteractiveObject input in childInputs)
        {
            foreach (RigidHand hand in hands)
            {
                if (hand.isActiveAndEnabled)
                {
                    foreach (RigidFinger finger in hand.fingers)
                    {
                        // Skip disabled fingers
                        if (!enableIndex && finger.name == "index" ||
                            !enableMiddle && finger.name == "middle" ||
                            !enableRing && finger.name == "ring" ||
                            !enablePinky && finger.name == "pinky" ||
                            !enableThumb && finger.name == "thumb")
                        {
                            continue;
                        }

                        if (input.Touchable)
                        {
                            Transform bone  = finger.bones[3];
                            Vector3   point = input.GetNearestPoint(bone.position);
                            float     dist  = Vector3.Distance(point, bone.position);

                            // If bone->point lines up with the normal, we're behind the interaction surface and treat distance as 0
                            // This is limited to points directly behind the surface, and within a reasonable distance
                            Vector3 delta = point - bone.position;
                            float   dot   = Vector3.Dot(delta, input.InteractionNormal);
                            if (dot > 0 && Mathf.Abs(dot) > dist - 0.01f && dist < 0.5f * hoverDistance)
                            {
                                dist = 0.0f;
                            }

                            if (dist < closestDist)
                            {
                                closestBone   = bone;
                                closestPoint  = point;
                                closestNormal = input.InteractionNormal;
                                closestDist   = dist;
                                targetInput   = input;
                            }
                        }
                    }
                }
            }
        }

        if (targetInput)
        {
            // Hover selection logic <THERE CAN BE ONLY ONE>
            // either there's no active, previous target...
            if (!_lastHovered || !_lastHovered.gameObject.activeInHierarchy)
            {
                targetInput.HoverEnter();
                _lastHovered = targetInput;
            }
            // ... or there was, but we switch away from it
            else if (_lastHovered != targetInput)
            {
                _lastHovered.HoverExit();
                targetInput.HoverEnter();
                _lastHovered = targetInput;
            }
            // Otherwise, we're hovering over an input, so update it
            else if (_lastHovered == targetInput)
            {
                _lastHovered.Hovering(closestBone.position);
            }

            // Get the actual interaction point
            interactionPoint = targetInput.GetInteractionPoint(closestPoint, effectorDim);
            if (displayTargetWidget && !ShouldHold())
            {
                displayTargetWidget.gameObject.SetActive(true);
                displayTargetWidget.position = interactionPoint;
                Vector3 normalTarget = interactionPoint + closestNormal;
                displayTargetWidget.LookAt(normalTarget);
            }
            if (displayBoneWidget)
            {
                displayBoneWidget.gameObject.SetActive(true);
                displayBoneWidget.position = closestBone.position;
            }
        }
        else if (activeHands == 1)
        {
            // Hand-follow behaviour
            // Only one hand to follow

            // Dehover
            if (_lastHovered)
            {
                _lastHovered.HoverExit();
                _lastHovered = null;
            }
            // move to offset from index finger
            if (displayTargetWidget && !ShouldHold())
            {
                displayTargetWidget.gameObject.SetActive(true);
                Vector3 offset = new Vector3(0.0f, 0.0f, 0.18f);
                // offset from index finger's end
                displayTargetWidget.position = activeHand.fingers[1].bones[3].transform.position + offset;
                // Reset normal direction
                displayTargetWidget.rotation = safeZone.transform.rotation;
            }

            if (displayBoneWidget)
            {
                displayBoneWidget.gameObject.SetActive(false);
            }
        }
        // No (or both) hands visible
        else
        {
            // Dehover
            if (_lastHovered)
            {
                _lastHovered.HoverExit();
                _lastHovered = null;
            }
            // Hide the arm (not used)
            RetractArm();
        }

        // Regardless of anything else, retract if touch is disabled
        if (!_touchActive)
        {
            RetractArm();
        }

        // Capacitive sensor update
        UpdateSensor();

        // Trigger next menu
        if (Input.GetButtonDown("Submit"))
        {
            _currentMenu.Next();
        }
    }