Пример #1
0
        //Cast an array of rays into '_direction' and centered around '_origin';
        private void CastRayArray(Vector3 _origin, Vector3 _direction)
        {
            //Calculate origin and direction of ray in world coordinates;
            Vector3 _rayStartPosition = Vector3.zero;
            Vector3 rayDirection      = GetCastDirection();

            //Clear results from last frame;
            arrayNormals.Clear();
            arrayPoints.Clear();

            RaycastHit _hit;

            //Cast array;
            for (int i = 0; i < raycastArrayStartPositions.Length; i++)
            {
                //Calculate ray start position;
                _rayStartPosition = _origin + tr.TransformDirection(raycastArrayStartPositions[i]);

                if (Physics.Raycast(_rayStartPosition, rayDirection, out _hit, castLength, layermask, QueryTriggerInteraction.Ignore))
                {
                    if (isInDebugMode)
                    {
                        Debug.DrawRay(_hit.point, _hit.normal, Color.red, Time.fixedDeltaTime * 1.01f);
                    }

                    hitColliders.Add(_hit.collider);
                    hitTransforms.Add(_hit.transform);
                    arrayNormals.Add(_hit.normal);
                    arrayPoints.Add(_hit.point);
                }
            }

            //Evaluate results;
            hasDetectedHit = (arrayPoints.Count > 0);

            if (hasDetectedHit)
            {
                //Calculate average surface normal;
                Vector3 _averageNormal = Vector3.zero;
                for (int i = 0; i < arrayNormals.Count; i++)
                {
                    _averageNormal += arrayNormals[i];
                }

                _averageNormal.Normalize();

                //Calculate average surface point;
                Vector3 _averagePoint = Vector3.zero;
                for (int i = 0; i < arrayPoints.Count; i++)
                {
                    _averagePoint += arrayPoints[i];
                }

                _averagePoint /= arrayPoints.Count;

                hitPosition = _averagePoint;
                hitNormal   = _averageNormal;
                hitDistance = VectorMath.ExtractDotVector(_origin - hitPosition, _direction).magnitude;
            }
        }
Пример #2
0
        //Helper functions;

        //Returns 'true' if vertical momentum is above a small threshold;
        private bool IsRisingOrFalling()
        {
            //Calculate current vertical momentum;
            Vector3 _verticalMomentum = VectorMath.ExtractDotVector(GetMomentum(), tr.up);

            //Setup threshold to check against;
            //For most applications, a value of '0.001f' is recommended;
            float _limit = 0.001f;

            //Return true if vertical momentum is above '_limit';
            return(_verticalMomentum.magnitude > _limit);
        }
Пример #3
0
        //Cast a sphere into '_direction' from '_origin';
        private void CastSphere(Vector3 _origin, Vector3 _direction)
        {
            RaycastHit _hit;

            hasDetectedHit = Physics.SphereCast(_origin, sphereCastRadius, _direction, out _hit, castLength - sphereCastRadius, layermask, QueryTriggerInteraction.Ignore);

            if (hasDetectedHit)
            {
                hitPosition = _hit.point;
                hitNormal   = _hit.normal;
                hitColliders.Add(_hit.collider);
                hitTransforms.Add(_hit.transform);

                hitDistance = _hit.distance;

                hitDistance += sphereCastRadius;

                //Calculate real distance;
                if (calculateRealDistance)
                {
                    hitDistance = VectorMath.ExtractDotVector(_origin - hitPosition, _direction).magnitude;
                }

                Collider _col = hitColliders[0];

                //Calculate real surface normal by casting an additional raycast;
                if (calculateRealSurfaceNormal)
                {
                    if (_col.Raycast(new Ray(hitPosition - _direction, _direction), out _hit, 1.5f))
                    {
                        if (Vector3.Angle(_hit.normal, -_direction) >= 89f)
                        {
                            hitNormal = backupNormal;
                        }
                        else
                        {
                            hitNormal = _hit.normal;
                        }
                    }
                    else
                    {
                        hitNormal = backupNormal;
                    }

                    backupNormal = hitNormal;
                }
            }
        }
Пример #4
0
        //Apply friction to both vertical and horizontal momentum based on 'friction' and 'gravity';
        //Handle sliding down steep slopes;
        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.IncrementVectorLengthTowardTargetLength(_horizontalMomentum, groundFriction, Time.deltaTime, 0f);
            }
            else
            {
                _horizontalMomentum = VectorMath.IncrementVectorLengthTowardTargetLength(_horizontalMomentum, airFriction, Time.deltaTime, 0f);
            }

            //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;
            }
        }