/// <summary> /// Checks whether <see cref="Character"/> is grounded. /// </summary> /// <remarks> /// <see cref="CharacterController.isGrounded"/> isn't accurate so this method does an additional check using <see cref="Physics"/>. /// </remarks> /// <returns>Whether <see cref="Character"/> is grounded.</returns> protected virtual bool CheckIfCharacterControllerIsGrounded() { if (Character.isGrounded) { return(true); } HeapAllocationFreeReadOnlyList <Collider> hitColliders = PhysicsCast.OverlapSphereAll( null, Character.transform.position + (Vector3.up * (Character.radius - Character.skinWidth - 0.001f)), Character.radius, 1 << Character.gameObject.layer); foreach (Collider hitCollider in hitColliders) { if (hitCollider != Character && hitCollider != RigidbodyCollider && !ignoredColliders.Contains(hitCollider) && !Physics.GetIgnoreLayerCollision( hitCollider.gameObject.layer, Character.gameObject.layer) && !Physics.GetIgnoreLayerCollision(hitCollider.gameObject.layer, PhysicsBody.gameObject.layer)) { return(true); } } return(false); }
/// <summary> /// Casts a ray from the <see cref="source"/> origin location towards the <see cref="target"/> destination location and determines whether the raycast is blocked by another <see cref="Collider"/>. /// </summary> public virtual void Process() { Vector3 difference = target.transform.position - source.transform.position; Ray ray = new Ray(source.transform.position, difference); RaycastHit[] raycastHits = PhysicsCast.RaycastAll( physicsCast, ray, difference.magnitude, Physics.IgnoreRaycastLayer); bool isObscured = raycastHits.Any(hit => hit.transform.gameObject != source && hit.collider != target); if (isObscured == wasPreviouslyObscured) { return; } wasPreviouslyObscured = isObscured; if (isObscured) { TargetObscured?.Invoke(raycastHits); } else { TargetUnobscured?.Invoke(); } }
/// <summary> /// Casts a ray to find the first collision. /// </summary> /// <param name="tracerRaycast">The ray to cast with.</param> /// <returns><see langword="true"/> if a valid surface is located.</returns> protected virtual bool FindFirstCollision(Ray tracerRaycast) { RaycastHit collision; if (PhysicsCast.Raycast(physicsCast, tracerRaycast, out collision, maximumDistance, Physics.IgnoreRaycastLayer)) { SetSurfaceData(collision); return(true); } return(false); }
/// <summary> /// Casts a ray to find all collisions. /// </summary> /// <param name="tracerRaycast">The ray to cast with.</param> /// <returns><see langword="true"/> if a valid surface is located.</returns> protected virtual bool FindAllCollisions(Ray tracerRaycast) { foreach (RaycastHit collision in PhysicsCast.RaycastAll(physicsCast, tracerRaycast, maximumDistance, Physics.IgnoreRaycastLayer).OrderBy(hit => hit.distance)) { if (ValidSurface(collision)) { SetSurfaceData(collision); return(true); } } return(false); }