public override Contact this[int index] { get { var contact = Contact.Create( startPosition, endPosition); contact.shape = null; Transform currentTransform = raycastHits[index].collider.transform; while (currentTransform != null) { if (currentTransform == collider.transform) { return(contact); } currentTransform = currentTransform.parent; } contact.contact = raycastHits[index]; contact.contactCollider = raycastHits[index].collider; contact.contactPoint = raycastHits[index].point; contact.contactNormal = raycastHits[index].normal; contact.contactDistance = raycastHits[index].distance; if (raycastHits[index].distance == 0f) { var(linePoint, colliderPoint) = ClosestPoint.FromLineSegment( contact.startPosition, contact.endPosition, contact.contactCollider, layerMask); if (Missing.IsNaN(colliderPoint)) { return(contact); } var delta = colliderPoint - linePoint; contact.contactOrigin = linePoint; contact.contactPoint = colliderPoint; contact.contactDistance = math.length(delta) - Radius; contact.contactPenetration = (contact.contactDistance < 0f); RaycastHit raycastHit; if (Raycast.ClosestHit( linePoint, math.normalizesafe(delta), out raycastHit, math.max(contact.contactDistance + Radius, Radius + 0.01f))) { contact.contactNormal = raycastHit.normal; } else if (contact.contactDistance < epsilon) { contact.contactNormal = math.normalizesafe(linePoint - colliderPoint); } } else { contact.contactOrigin = ClosestPoint.FromPosition( contact.contactPoint, contact.startPosition, contact.endPosition); } contact.contactNormal = math.normalizesafe(contact.contactOrigin - contact.contactPoint); contact.shape = this; return(contact); } }
float GetGroundDistance(float3 position) { var rayStartPosition = position + (math.up() * groundProbeOffset); var rayDirection = -math.up(); var rayLength = groundProbeOffset + groundProbeLength; bool isGrounded = false; RaycastHit raycast; var rayCastResult = Raycast.ClosestHit( rayStartPosition, rayDirection, out raycast, rayLength, layerMask, transform); var distance = float.MaxValue; if (rayCastResult) { var tolerance = (groundSnap ? groundSnapDistance : groundTolerance); isGrounded = raycast.distance - groundProbeOffset < tolerance + epsilon; distance = raycast.distance - groundProbeOffset; state.current.ground = raycast.collider.transform; } if (!isGrounded) { float3 closestPoint = raycast.point; rayStartPosition = position + (math.up() * groundSupport); Collider[] colliders = null; int numContacts = Intersection.OverlapSphere( rayStartPosition, groundSupport * oneOverCos45, out colliders, layerMask, transform); bool ignore = false; if (colliders == null || numContacts == 0) { ignore = true; isGrounded = false; } else if (numContacts == 1) { var result = ClosestPoint.FromPosition( position + math.up() * 0.05f, colliders[0]); if (!Missing.IsNaN(result)) { closestPoint = result; var closestPointLocal = state.current.InverseTransformPoint(closestPoint); closestPointLocal.y = 0f; if (closestPointLocal.magnitude < groundSupport) { ignore = false; isGrounded = true; } else { ignore = true; isGrounded = false; } } } else { for (int i = 0; i < numContacts; i++) { if (colliders[i] == raycast.collider) { continue; } var candidatePoint = ClosestPoint.FromPosition( position + math.up() * 0.05f, colliders[i]); if (Missing.IsNaN(candidatePoint)) { continue; } var candidatePointLocal = state.current.InverseTransformPoint(candidatePoint); if (candidatePointLocal.y >= groundSupport + epsilon) { continue; } candidatePointLocal.y = 0f; if (math.length(candidatePointLocal) < groundSupport) { closestPoint = candidatePoint; isGrounded = true; break; } } } if (!ignore) { var closestPointLocal = state.current.InverseTransformPoint(closestPoint); rayStartPosition = closestPoint + (math.up() * groundSupport); rayDirection = -math.up(); rayLength = groundSupport + groundTolerance; rayCastResult = Raycast.ClosestHit( rayStartPosition, rayDirection, out raycast, rayLength, layerMask, transform); if (rayCastResult) { distance = raycast.distance - groundSupport - closestPointLocal.y; isGrounded = distance < (groundTolerance + epsilon) * oneOverCos45; state.current.ground = raycast.collider.gameObject.transform; } } } return(distance); }
public override Contact this[int index] { get { var contact = Contact.Create( startPosition, float3.zero); contact.shape = null; Transform currentTransform = raycastHits[index].collider.transform; if (currentTransform == collider.transform) { return(contact); } while (currentTransform != null) { if (currentTransform == collider.transform) { return(contact); } currentTransform = currentTransform.parent; } contact.contact = raycastHits[index]; contact.contactOrigin = contact.startPosition; contact.contactCollider = raycastHits[index].collider; contact.contactPoint = raycastHits[index].point; contact.contactNormal = raycastHits[index].normal; contact.contactDistance = raycastHits[index].distance; if (raycastHits[index].distance == 0f) { var colliderPoint = ClosestPoint.FromPosition(contact.startPosition, contact.contactCollider, layerMask); if (Missing.IsNaN(colliderPoint)) { return(contact); } float3 delta = colliderPoint - contact.startPosition; if (math.abs(math.length(delta) - Radius) < epsilon) { float dot = math.dot(math.normalizesafe(delta), direction); if (dot <= -0.8f) { return(contact); } } contact.contactOrigin = contact.startPosition; contact.contactPoint = colliderPoint; contact.contactDistance = math.length(delta) - Radius; contact.contactPenetration = (contact.contactDistance < 0f); RaycastHit raycastHit; if (Raycast.ClosestHit(contact.startPosition, math.normalizesafe(delta), out raycastHit, Mathf.Max(contact.contactDistance + Radius, Radius + 0.01f))) { contact.contactNormal = raycastHit.normal; } else if (contact.contactDistance < epsilon) { contact.contactNormal = math.normalizesafe(contact.startPosition - colliderPoint); } } if (!Missing.equalEps(direction, -Missing.up, epsilon)) { RaycastHit raycastHit; if (Raycast.ClosestHit(contact.contactPoint - (direction * distance), direction, out raycastHit, distance + Radius, -1, collider.transform)) { contact.contactNormal = raycastHit.normal; } } contact.shape = this; return(contact); } }
void InitializeSupport(float3 position) { var rayStartPosition = position + (math.up() * groundProbeOffset); var rayDirection = -math.up(); var rayLength = groundProbeOffset + groundProbeLength; RaycastHit raycast; bool isGrounded = Raycast.ClosestHit( rayStartPosition, rayDirection, out raycast, rayLength, layerMask, transform); if (isGrounded) { isGrounded = (raycast.distance - groundProbeOffset < groundTolerance + epsilon); state.current.ground = raycast.collider.gameObject.transform; rayLength = raycast.distance + groundSupport; } if (!isGrounded) { float3 closestPoint = raycast.point; rayStartPosition = position + (math.up() * groundSupport); Collider[] colliders = null; var numContacts = Intersection.OverlapSphere( rayStartPosition, groundSupport * oneOverCos45, out colliders, layerMask, transform); bool ignore = false; if (colliders == null || numContacts == 0) { ignore = true; isGrounded = false; } else if (numContacts == 1) { var result = ClosestPoint.FromPosition( rayStartPosition, colliders[0]); if (!Missing.IsNaN(result)) { closestPoint = result; var closestPointLocal = state.current.InverseTransformPoint( closestPoint); closestPointLocal.y = 0f; if (closestPointLocal.magnitude > (groundSupport * 0.25f)) { ignore = true; isGrounded = false; } } } else { for (int i = 0; i < numContacts; i++) { if (colliders[i] == raycast.collider) { continue; } var candidatePoint = ClosestPoint.FromPosition( rayStartPosition, colliders[i]); if (Missing.IsNaN(candidatePoint)) { continue; } var candidatePointLocal = state.current.InverseTransformPoint(candidatePoint); if (candidatePointLocal.y >= groundSupport + epsilon) { continue; } if (-candidatePointLocal.y > groundTolerance + epsilon) { continue; } candidatePointLocal.y = 0f; if (math.length(candidatePointLocal) < (groundSupport * 0.25f)) { closestPoint = candidatePoint; isGrounded = true; break; } } } if (!ignore) { var closestPointToRayStart = closestPoint - rayStartPosition; rayDirection = math.normalizesafe(closestPointToRayStart); rayLength = math.length(closestPointToRayStart) + groundTolerance; var rayCastResult = Raycast.ClosestHit( rayStartPosition, rayDirection, out raycast, rayLength, layerMask, transform); if (rayCastResult) { float groundDistance = raycast.distance - groundSupport; isGrounded = groundDistance < (groundTolerance + epsilon) * oneOverCos45; state.current.ground = raycast.collider.gameObject.transform; } } } state.current.isGrounded = isGrounded; }