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