/// <summary>
        /// Performs a collision test in any of the four cardinal directions.
        /// </summary>
        public CollisionHitInfo CardinalCollision(CardinalCollisionType cardinalCollisionType, float skin, float extraDistance, LayerMask layerMask)
        {
            CollisionHitInfo hitInfo = new CollisionHitInfo();

            hitInfo.Reset();

            Vector3 origin = Vector3.zero;

            float castDistance = skin + extraDistance;

            Vector3 direction = Vector3.zero;

            Vector3 center = characterBody.bodyTransform.Position + characterBody.bodyTransform.Up * characterBody.heightExtents;

            switch (cardinalCollisionType)
            {
            case CardinalCollisionType.Up:
                direction = characterBody.bodyTransform.Up;
                origin    = center + direction * (characterBody.height / 2 - skin);
                break;

            case CardinalCollisionType.Down:
                direction = -characterBody.bodyTransform.Up;
                origin    = center + direction * (characterBody.height / 2 - skin);
                break;

            case CardinalCollisionType.Left:
                direction = -characterBody.bodyTransform.Right;
                origin    = center + direction * (characterBody.width / 2 - skin);
                break;

            case CardinalCollisionType.Right:
                direction = characterBody.bodyTransform.Right;
                origin    = center + direction * (characterBody.width / 2 - skin);
                break;
            }



            hitInfo = PhysicsUtilities.Raycast(
                is3D,
                origin,
                direction,
                castDistance,
                layerMask
                );



            return(hitInfo);
        }
Beispiel #2
0
        public static CollisionHitInfo RaycastSweep(bool is3D, Vector3 start, Vector3 end, float numberOfRays, Vector3 castDirection, float castDistance, RaySelectionRule rule, LayerMask layerMask)
        {
            CollisionHitInfo hitInfo = new CollisionHitInfo();

            hitInfo.Reset();

            float   castArea            = Vector3.Magnitude(end - start);
            Vector3 startToEndDirection = (end - start).normalized;

            hitInfo.distance = castDistance;

            CollisionHitInfo currentHitInfo;

            float step = castArea / (numberOfRays - 1);

            for (int i = 0; i < numberOfRays; i++)
            {
                Vector3 rayOrigin = start + startToEndDirection * step * i;

                // Debug.DrawRay( rayOrigin , castDirection * castDistance , Color.magenta );

                currentHitInfo = PhysicsUtilities.Raycast(
                    is3D,
                    rayOrigin,
                    castDirection,
                    castDistance,
                    layerMask
                    );


                if (!currentHitInfo.collision)
                {
                    continue;
                }

                switch (rule)
                {
                case RaySelectionRule.Shortest:

                    if (currentHitInfo.distance < hitInfo.distance)
                    {
                        hitInfo = currentHitInfo;
                    }

                    break;

                case RaySelectionRule.ShortestNonZero:

                    if (currentHitInfo.distance != 0 && currentHitInfo.distance < hitInfo.distance)
                    {
                        hitInfo = currentHitInfo;
                    }
                    break;

                case RaySelectionRule.Longest:

                    if (currentHitInfo.distance > hitInfo.distance)
                    {
                        hitInfo = currentHitInfo;
                    }

                    break;
                }
            }

            return(hitInfo);
        }
        /// <summary>
        /// Performs the collision detection method used to align the character to the ground.
        /// </summary>
        public GroundAlignmentResult GroundRaysCollisions(float skin, float extraDistance, float maxSlopeAngle, LayerMask layerMask)
        {
            GroundAlignmentResult result = new GroundAlignmentResult();

            result.Reset();

            CollisionHitInfo leftHitInfo;
            CollisionHitInfo rightHitInfo;


            if (extraDistance < 0)
            {
                return(result);
            }

            float castDistance = skin + extraDistance;

            Vector3 leftRayOrigin  = characterBody.bodyTransform.Position - characterBody.bodyTransform.Right * characterBody.verticalArea / 2 + characterBody.bodyTransform.Up * skin;
            Vector3 rightRayOrigin = characterBody.bodyTransform.Position + characterBody.bodyTransform.Right * characterBody.verticalArea / 2 + characterBody.bodyTransform.Up * skin;


            leftHitInfo = PhysicsUtilities.Raycast(
                is3D,
                leftRayOrigin,
                -characterBody.bodyTransform.Up,
                castDistance,
                layerMask
                );

            rightHitInfo = PhysicsUtilities.Raycast(
                is3D,
                rightRayOrigin,
                -characterBody.bodyTransform.Up,
                castDistance,
                layerMask
                );


            float leftLocalSlopeSignedAngle = Utilities.SignedAngle(characterBody.bodyTransform.Up, leftHitInfo.normal, characterBody.bodyTransform.Forward);
            float leftLocalSlopeAngle       = Mathf.Abs(leftLocalSlopeSignedAngle);

            float rightLocalSlopeSignedAngle = Utilities.SignedAngle(characterBody.bodyTransform.Up, rightHitInfo.normal, characterBody.bodyTransform.Forward);
            float rightLocalSlopeAngle       = Mathf.Abs(rightLocalSlopeSignedAngle);



            if ((leftHitInfo.collision && Utilities.isCloseTo(leftLocalSlopeAngle, 90, 0.01f)) ||
                (rightHitInfo.collision && Utilities.isCloseTo(rightLocalSlopeAngle, 90, 0.01f)))
            {
                return(result);
            }


            // Left result
            result.leftRay.collision = leftHitInfo.collision;
            if (leftHitInfo.collision)
            {
                result.leftRay.point    = leftHitInfo.point;
                result.leftRay.distance = leftHitInfo.distance;
                result.leftRay.normal   = leftHitInfo.normal;
                result.leftRay.verticalSlopeSignedAngle = Utilities.SignedAngle(characterMotor.CurrentVerticalDirection, leftHitInfo.normal, characterBody.bodyTransform.Forward);
                result.leftRay.verticalSlopeAngle       = Mathf.Abs(result.leftRay.verticalSlopeSignedAngle);
                result.leftRay.stable = result.leftRay.verticalSlopeAngle <= maxSlopeAngle;
            }
            else
            {
                result.leftRay.Reset();
            }


            // Right result
            result.rightRay.collision = rightHitInfo.collision;
            if (rightHitInfo.collision)
            {
                result.rightRay.point    = rightHitInfo.point;
                result.rightRay.distance = rightHitInfo.distance;
                result.rightRay.normal   = rightHitInfo.normal;
                result.rightRay.verticalSlopeSignedAngle = Utilities.SignedAngle(characterMotor.CurrentVerticalDirection, rightHitInfo.normal, characterBody.bodyTransform.Forward);
                result.rightRay.verticalSlopeAngle       = Mathf.Abs(result.rightRay.verticalSlopeSignedAngle);
                result.rightRay.stable = result.rightRay.verticalSlopeAngle <= maxSlopeAngle;
            }
            else
            {
                result.rightRay.Reset();
            }

            return(result);
        }