Esempio n. 1
0
        /// <summary>
        /// Local method to move to the target position/rotation at the move speed. The onComplete action will be called after the character has arrived.
        /// </summary>
        /// <param name="targetPosition">The target position.</param>
        /// <param name="targetRotation">The target rotation.</param>
        /// <param name="minMoveSpeed">The minimum speed to move positions.</param>
        /// <param name="onComplete">The action to call after the character has arrived.</param>
        private IEnumerator MoveToTargetLocal(Vector3 targetPosition, Quaternion targetRotation, float minMoveSpeed, Action onComplete)
        {
            if (s_EndOfFrame == null)
            {
                s_EndOfFrame = new WaitForFixedUpdate();
            }

            // Use the existing speed if it is greater then the minimum so the character will smoothly move to the target.
            var moveSpeed = m_Controller.InputVector.magnitude > minMoveSpeed ? m_Controller.InputVector.magnitude : minMoveSpeed;

            // Stop any existing velocities.
            m_Controller.StopMovement();

            // Gradually move towards the target position/rotation.
            var prevPosition = m_Transform.position;
            var startOffset  = m_Transform.InverseTransformPoint(targetPosition);

            while (true)
            {
                // Rotate towards the target rotation.
                m_Controller.SetRotation(Quaternion.Slerp(m_Transform.rotation, targetRotation, m_Controller.RotationSpeed * Time.deltaTime));

                // Use Root Motion to determine how far to move.
                var position = m_Transform.position;
                position.x = Mathf.MoveTowards(position.x, targetPosition.x, m_Controller.RootMotionForce.x > 0.05f ? m_Controller.RootMotionForce.x : 0.05f);
                position.z = Mathf.MoveTowards(position.z, targetPosition.z, m_Controller.RootMotionForce.z > 0.05f ? m_Controller.RootMotionForce.z : 0.05f);
                m_Controller.SetPosition(position);

                // Keep walking towards the target position. Slow down as the character gets closer.
                var offset   = m_Transform.InverseTransformPoint(targetPosition);
                var strength = (startOffset.x < 0.001f ? 0 : offset.x / startOffset.x);
                m_AnimatorMonitor.SetHorizontalInputValue(moveSpeed * strength);
                strength = (startOffset.z < 0.001f ? 0 : offset.z / startOffset.z);
                m_AnimatorMonitor.SetForwardInputValue(moveSpeed * strength);

                // Break if the character has arrived at the destination. Perform the check after the movements so it doesn't have to wait for a frame to pass before checking again.
                if (Mathf.Abs(m_Transform.position.x - targetPosition.x) < 0.1f && Mathf.Abs(m_Transform.position.z - targetPosition.z) < 0.1f &&
                    Quaternion.Angle(m_Transform.rotation, targetRotation) < 0.1f)
                {
                    break;
                }

                // If the character is stuck then stop trying to move.
                if ((position - prevPosition).sqrMagnitude < 0.00001f)
                {
                    break;
                }

                prevPosition = position;
                yield return(s_EndOfFrame);
            }

            // The character has arrived. Set the position and rotation to its final position.
            m_Controller.SetPosition(targetPosition);
            m_Controller.SetRotation(targetRotation);
            // The character is no longer moving.
            m_Controller.StopMovement();

            // The coroutine has ended.
            m_MoveToTargetRoutine = null;

            // Let the calling ability know that the character has arrived.
            onComplete();
        }