Exemplo n.º 1
0
        private void UpdateMovement(float deltaTime)
        {
            tempMoveVelocity   = Vector3.zero;
            tempMoveDirection  = Vector3.zero;
            tempTargetDistance = 0f;

            // Update airborne elasped
            if (CacheOpenCharacterController.isGrounded)
            {
                airborneElapsed = 0f;
            }
            else
            {
                airborneElapsed += deltaTime;
            }

            bool isGrounded = CacheOpenCharacterController.isGrounded || airborneElapsed < airborneDelay;

            if (isGrounded || !canFly)
            {
                isFlying = false;
            }

            if (HasNavPaths)
            {
                // Set `tempTargetPosition` and `tempCurrentPosition`
                tempTargetPosition    = navPaths.Peek();
                tempCurrentPosition   = CacheTransform.position;
                tempTargetPosition.y  = 0;
                tempCurrentPosition.y = 0;
                tempMoveDirection     = tempTargetPosition - tempCurrentPosition;
                tempMoveDirection.Normalize();
                tempTargetDistance = Vector3.Distance(tempTargetPosition, tempCurrentPosition);
                if (tempTargetDistance < StoppingDistance)
                {
                    navPaths.Dequeue();
                    if (!HasNavPaths)
                    {
                        StopMove();
                    }
                }
                else
                {
                    // Turn character to destination
                    yRotation = Quaternion.LookRotation(tempMoveDirection).eulerAngles.y;
                }
            }

            // If move by WASD keys, set move direction to input direction
            if (tempInputDirection.sqrMagnitude > 0f)
            {
                tempMoveDirection = tempInputDirection;
                tempMoveDirection.Normalize();
            }

            if (!CacheEntity.CanMove())
            {
                tempMoveDirection = Vector3.zero;
                isJumping         = false;
                applyingJumpForce = false;
            }

            // Prepare movement speed
            tempEntityMoveSpeed = applyingJumpForce ? 0f : CacheEntity.GetMoveSpeed();
            if (isUnderWater)
            {
                isFlying = false;
            }
            tempCurrentMoveSpeed = tempEntityMoveSpeed * (isFlying ? flySpeed : isUnderWater ? swimSpeed : 1f);
            // Calculate vertical velocity by gravity
            if (!isGrounded && !isFlying)
            {
                if (!isUnderWater || submergence <= underWaterThreshold)
                {
                    if (!useRootMotionForFall)
                    {
                        tempVerticalVelocity = Mathf.MoveTowards(tempVerticalVelocity, -maxFallVelocity, gravity * deltaTime);
                    }
                    else
                    {
                        tempVerticalVelocity = 0f;
                    }
                }
                else
                {
                    tempVerticalVelocity = 0f;
                }
            }
            else
            {
                tempVerticalVelocity = 0f;
            }

            // Jumping
            if (!isFlying && (isUnderWater || isGrounded) && isJumping)
            {
                if (!isUnderWater || submergence <= underWaterThreshold)
                {
                    airborneElapsed = airborneDelay;
                    CacheEntity.CallAllPlayJumpAnimation();
                    applyingJumpForce       = true;
                    applyJumpForceCountDown = 0f;
                    switch (applyJumpForceMode)
                    {
                    case ApplyJumpForceMode.ApplyAfterFixedDuration:
                        applyJumpForceCountDown = applyJumpForceFixedDuration;
                        break;

                    case ApplyJumpForceMode.ApplyAfterJumpDuration:
                        if (CacheEntity.Model is IJumppableModel)
                        {
                            applyJumpForceCountDown = (CacheEntity.Model as IJumppableModel).GetJumpAnimationDuration();
                        }
                        break;
                    }
                }
            }

            if (applyingJumpForce)
            {
                applyJumpForceCountDown -= Time.deltaTime;
                if (applyJumpForceCountDown <= 0f)
                {
                    applyingJumpForce = false;
                    if (!useRootMotionForJump)
                    {
                        tempVerticalVelocity = CalculateJumpVerticalSpeed();
                    }
                }
            }
            // Updating horizontal movement (WASD inputs)
            if (tempMoveDirection.sqrMagnitude > 0f)
            {
                // Calculate only horizontal move direction
                tempHorizontalMoveDirection   = tempMoveDirection;
                tempHorizontalMoveDirection.y = 0;
                tempHorizontalMoveDirection.Normalize();

                // If character move backward
                if (Vector3.Angle(tempHorizontalMoveDirection, CacheTransform.forward) > 120)
                {
                    tempCurrentMoveSpeed *= backwardMoveSpeedRate;
                }

                if (HasNavPaths)
                {
                    // NOTE: `tempTargetPosition` and `tempCurrentPosition` were set above
                    tempSqrMagnitude        = (tempTargetPosition - tempCurrentPosition).sqrMagnitude;
                    tempPredictPosition     = tempCurrentPosition + (tempHorizontalMoveDirection * tempCurrentMoveSpeed * deltaTime);
                    tempPredictSqrMagnitude = (tempPredictPosition - tempCurrentPosition).sqrMagnitude;
                    // Check `tempSqrMagnitude` against the `tempPredictSqrMagnitude`
                    // if `tempPredictSqrMagnitude` is greater than `tempSqrMagnitude`,
                    // rigidbody will reaching target and character is moving pass it,
                    // so adjust move speed by distance and time (with physic formula: v=s/t)
                    if (tempPredictSqrMagnitude >= tempSqrMagnitude)
                    {
                        tempCurrentMoveSpeed *= tempTargetDistance / deltaTime / tempCurrentMoveSpeed;
                    }
                    tempMoveVelocity = tempHorizontalMoveDirection * tempCurrentMoveSpeed;
                }
                else
                {
                    // Move with wasd keys so it does not have to adjust speed
                    tempMoveVelocity = tempHorizontalMoveDirection * tempCurrentMoveSpeed;
                }
            }

            // Updating vertical movement (Fall, WASD inputs under water)
            if (isUnderWater || isFlying)
            {
                if (submergence >= underWaterThreshold || shouldDive || isFlying)
                {
                    tempMoveVelocity.y = tempMoveDirection.y * tempCurrentMoveSpeed;
                    shouldDive         = false;
                }
                else
                {
                    float distanceFromThreshold = underWaterThreshold - submergence;
                    float bouyantVelocity       = 0.01f;
                    if (distanceFromThreshold > 0.01)
                    {
                        bouyantVelocity = -(distanceFromThreshold / deltaTime / tempCurrentMoveSpeed);
                    }
                    tempMoveVelocity.y = bouyantVelocity + (tempVerticalVelocity > 0 ? tempVerticalVelocity : 0f);
                }
                if (InputManager.GetButton("Crouch") || tempMoveDirection.y < -0.8)
                {
                    shouldDive = true;
                }
            }
            else
            {
                // Update velocity while not under water
                tempMoveVelocity.y = tempVerticalVelocity;
            }

            collisionFlags = CacheOpenCharacterController.Move(tempMoveVelocity * deltaTime);
            if ((collisionFlags & CollisionFlags.CollidedBelow) == CollisionFlags.CollidedBelow ||
                (collisionFlags & CollisionFlags.CollidedAbove) == CollisionFlags.CollidedAbove)
            {
                // Hit something below or above, falling in next frame
                tempVerticalVelocity = 0f;
            }

            UpdateRotation();
            isJumping = false;
        }