Пример #1
0
        private void FixedUpdate()
        {
            if (_controller == null)
            {
                return;
            }

            if (Anchor == null)
            {
                _transition *= 0.875f;
                if (_transition <= 0.01f)
                {
                    _transition = 0f;
                }
            }
            else
            {
                _transition = Mathf.Lerp(_transition, 1f, 0.125f);
            }

            if (Anchor == null && _transition <= 0f)
            {
                if (MatchRotation)
                {
                    _xform.rotation = _controller.Rotation;
                }
                if (MatchPosition)
                {
                    _xform.position = _controller.Position;
                }
            }
            else
            {
                var hand = _controller.Hand;
                if (MatchPosition)
                {
                    var offsetPos = _xform.position - _attachPoint.Position;
                    //_xform.position = Anchor.GetPosition(hand) + offsetPos;
                    if (Anchor != null)
                    {
                        _targetPos = Anchor.GetPosition(hand) + offsetPos;
                    }
                    _xform.position = Vector3.Lerp(_controller.Position, _targetPos, _transition);
                }

                if (MatchRotation)
                {
                    //_xform.rotation = Anchor.GetRotation(hand);
                    if (Anchor != null)
                    {
                        _targetRot = Anchor.GetRotation(hand);
                    }
                    _xform.rotation = Quaternion.Lerp(_controller.Rotation, _targetRot, _transition);
                }
            }
        }
Пример #2
0
        private void FixedUpdate()
        {
            if (DisableForce)
            {
                return;
            }
            if (_grabbedBody && _handBody)
            {
                bool isTwoHanded = _secondTarget && (_secondAnchor != null);

                // How far is the grabbed anchor from the hand?
                var mass  = _grabbedBody.mass * (isTwoHanded ? 0.5f : 1f);
                var delta = (_target.position - _grabbedAnchor.GetPosition(_firstGrabbedBy)) * (_moveSpeed / (1f + mass));

                // Find the angular delta
                Quaternion angDelta;

                //TODO  Calculate hand velocity in HandController and use that instead
                //TODO  Should be a blend of both hands' velocities for two-handed
                var handVelocity    = _handBody.velocity;
                var handAngVelocity = _handBody.angularVelocity;

                // Move the object towards the hand(s)
                if (_engaged < 1f)
                {
                    _engaged = Mathf.Lerp(_engaged, 1f, 0.125f);
                }

                if (isTwoHanded)
                {
                    // Two hands are manipulating this object...
                    var secondHand      = _firstGrabbedBy == Hand.Left ? Hand.Right : Hand.Left;
                    var secondAnchorPos = _secondAnchor.GetPosition(secondHand);

                    // Blend the position deltas of the each hand compared to its anchor
                    var delta2 = (_secondTarget.position - secondAnchorPos) * (_moveSpeed / (1f + _grabbedBody.mass));
                    delta = Vector3.LerpUnclamped(delta, delta2, 0.5f * _engaged);

                    // TODO  Calculate stretch, twist and bend
                    // TODO  Add option to auto-release second hand if stretch goes beyond a tolerance.  Priority could be specified by GrabAnchors

                    // Find the angle between the anchors
                    var fromDir = (_grabbedAnchor.GetPosition(_firstGrabbedBy) - secondAnchorPos).normalized;
                    var fromUp  = _secondAnchor.GetUp(secondHand);
                    var from    = Quaternion.LookRotation(fromDir, fromUp);

                    // Find the angle between the hands
                    var toDir = (_target.position - secondAnchorPos).normalized;
                    var toUp  = Vector3.Lerp(_target.up, _secondTarget.up, 0.5f).normalized;
                    var to    = Quaternion.LookRotation(toDir, toUp);

                    // Find the difference between those angles to turn both anchors towards their respective hands
                    angDelta = to * Quaternion.Inverse(from);
                }
                else
                {
                    angDelta = _target.rotation * Quaternion.Inverse(_grabbedAnchor.GetRotation(_firstGrabbedBy));
                }


                //! Not sure if there's any difference between these two in terms of natural behavior
                //_grabbedBody.velocity = Vector3.Lerp(_grabbedBody.velocity, delta + handVelocity, _engaged);
                _grabbedBody.AddForce(Vector3.Lerp(_grabbedBody.velocity, delta + handVelocity, _engaged) - _grabbedBody.velocity, ForceMode.VelocityChange);

                // Convert angular delta from Quaternion to Angle/Axis
                angDelta.ToAngleAxis(out float angle, out Vector3 axis);

                // Check that we're not already aligned
                if (float.IsInfinity(axis.x))
                {
                    return;
                }

                // Apply angular velocity to align the object to the hand controller(s)
                if (angle > 180f)
                {
                    angle -= 360f;
                }
                var magnitude = (_turnSpeed * Mathf.Deg2Rad * angle / Time.fixedUnscaledDeltaTime);
                var newAngVel = magnitude * axis.normalized;
                _grabbedBody.angularVelocity = Vector3.Lerp(_grabbedBody.angularVelocity, newAngVel, _engaged);
                _grabbedBody.AddTorque(handAngVelocity, ForceMode.VelocityChange);
            }
            else
            {
                // Nothing is grabbed, so disengage
                _engaged = 0f;
            }
        }