예제 #1
0
        //Apply friction to both vertical and horizontal momentum based on 'friction' and 'gravity';
        //Handle sliding down steep slopes;
        private void HandleMomentum()
        {
            //If local momentum is used, transform momentum into world coordinates first;
            if (useLocalMomentum)
            {
                momentum = tr.localToWorldMatrix * momentum;
            }

            Vector3 _verticalMomentum   = Vector3.zero;
            Vector3 _horizontalMomentum = Vector3.zero;

            //Split momentum into vertical and horizontal components;
            if (momentum != Vector3.zero)
            {
                _verticalMomentum   = VectorMath.ExtractDotVector(momentum, tr.up);
                _horizontalMomentum = momentum - _verticalMomentum;
            }

            //Add gravity to vertical momentum;
            _verticalMomentum -= tr.up * gravity * Time.deltaTime;

            //Remove any downward force if the controller is grounded;
            if (currentControllerState == ControllerState.Grounded)
            {
                _verticalMomentum = Vector3.zero;
            }

            //Apply friction to horizontal momentum based on whether the controller is grounded;
            if (currentControllerState == ControllerState.Grounded)
            {
                _horizontalMomentum = VectorMath.IncrementVectorTowardTargetVector(_horizontalMomentum, groundFriction, Time.deltaTime, Vector3.zero);
            }
            else
            {
                _horizontalMomentum = VectorMath.IncrementVectorTowardTargetVector(_horizontalMomentum, airFriction, Time.deltaTime, Vector3.zero);
            }

            //Add horizontal and vertical momentum back together;
            momentum = _horizontalMomentum + _verticalMomentum;

            //Project the current momentum onto the current ground normal if the controller is sliding down a slope;
            if (currentControllerState == ControllerState.Sliding)
            {
                momentum = Vector3.ProjectOnPlane(momentum, mover.GetGroundNormal());
            }

            //Apply slide gravity along ground normal, if controller is sliding;
            if (currentControllerState == ControllerState.Sliding)
            {
                Vector3 _slideDirection = Vector3.ProjectOnPlane(-tr.up, mover.GetGroundNormal()).normalized;
                momentum += _slideDirection * slideGravity * Time.deltaTime;
            }

            //If controller is jumping, override vertical velocity with jumpSpeed;
            if (currentControllerState == ControllerState.Jumping)
            {
                momentum  = VectorMath.RemoveDotVector(momentum, tr.up);
                momentum += tr.up * jumpSpeed;
            }

            if (useLocalMomentum)
            {
                momentum = tr.worldToLocalMatrix * momentum;
            }
        }
예제 #2
0
        //Determine current controller state based on current momentum and whether the controller is grounded (or not);
        //Handle state transitions;
        private ControllerState DetermineControllerState()
        {
            //Check if vertical momentum is pointing upwards;
            bool _isRising = IsRisingOrFalling() && (VectorMath.GetDotProduct(GetMomentum(), tr.up) > 0f);
            //Check if controller is sliding;
            bool _isSliding = mover.IsGrounded() && IsGroundTooSteep();

            //Grounded;
            if (currentControllerState == ControllerState.Grounded)
            {
                if (_isRising)
                {
                    OnGroundContactLost();
                    return(ControllerState.Rising);
                }
                if (!mover.IsGrounded())
                {
                    OnGroundContactLost();
                    return(ControllerState.Falling);
                }
                if (_isSliding)
                {
                    return(ControllerState.Sliding);
                }
                return(ControllerState.Grounded);
            }

            //Falling;
            if (currentControllerState == ControllerState.Falling)
            {
                if (_isRising)
                {
                    return(ControllerState.Rising);
                }
                if (mover.IsGrounded() && !_isSliding)
                {
                    OnGroundContactRegained(momentum);
                    return(ControllerState.Grounded);
                }
                if (_isSliding)
                {
                    OnGroundContactRegained(momentum);
                    return(ControllerState.Sliding);
                }
                return(ControllerState.Falling);
            }

            //Sliding;
            if (currentControllerState == ControllerState.Sliding)
            {
                if (_isRising)
                {
                    OnGroundContactLost();
                    return(ControllerState.Rising);
                }
                if (!mover.IsGrounded())
                {
                    return(ControllerState.Falling);
                }
                if (mover.IsGrounded() && !_isSliding)
                {
                    OnGroundContactRegained(momentum);
                    return(ControllerState.Grounded);
                }
                return(ControllerState.Sliding);
            }

            //Rising;
            if (currentControllerState == ControllerState.Rising)
            {
                if (!_isRising)
                {
                    if (mover.IsGrounded() && !_isSliding)
                    {
                        OnGroundContactRegained(momentum);
                        return(ControllerState.Grounded);
                    }
                    if (_isSliding)
                    {
                        return(ControllerState.Sliding);
                    }
                    if (!mover.IsGrounded())
                    {
                        return(ControllerState.Falling);
                    }
                }

                //If a ceiling detector has been attached to this gameobject, check for ceiling hits;
                if (ceilingDetector != null)
                {
                    if (ceilingDetector.HitCeiling())
                    {
                        OnCeilingContact();
                        return(ControllerState.Falling);
                    }
                }
                return(ControllerState.Rising);
            }

            //Jumping;
            if (currentControllerState == ControllerState.Jumping)
            {
                //Check for jump timeout;
                if ((Time.time - currentJumpStartTime) > jumpDuration)
                {
                    return(ControllerState.Rising);
                }

                //Check if jump key was let go;
                if (jumpKeyWasLetGo)
                {
                    return(ControllerState.Rising);
                }

                //If a ceiling detector has been attached to this gameobject, check for ceiling hits;
                if (ceilingDetector != null)
                {
                    if (ceilingDetector.HitCeiling())
                    {
                        OnCeilingContact();
                        return(ControllerState.Falling);
                    }
                }
                return(ControllerState.Jumping);
            }

            return(ControllerState.Falling);
        }