/// <summary> /// Generates the points for the cast. /// </summary> protected virtual void GeneratePoints() { Ray ray = new Ray(origin.transform.position, origin.transform.forward); RaycastHit hitData; bool hasCollided = PhysicsCast.Raycast(physicsCast, ray, out hitData, maximumLength, Physics.IgnoreRaycastLayer); TargetHit = (hasCollided ? hitData : (RaycastHit?)null); points[0] = origin.transform.position; points[1] = (hasCollided ? hitData.point : origin.transform.position + origin.transform.forward * maximumLength); }
/// <inheritdoc /> public override void CastPoints() { if (!isActiveAndEnabled) { return; } Ray ray = new Ray(transform.position, transform.forward); RaycastHit hitData; bool hasCollided = PhysicsCast.Raycast(physicsCast, ray, out hitData, maximumLength, Physics.IgnoreRaycastLayer); TargetHit = (hasCollided ? hitData : (RaycastHit?)null); points[0] = transform.position; points[1] = (hasCollided ? hitData.point : transform.position + transform.forward * maximumLength); ResultsChanged?.Invoke(eventData.Set(TargetHit, Points)); }
/// <summary> /// Checks for collisions along the parabolic line segments and generates the final points. /// </summary> /// <param name="forward">The forward direction to use for the checks.</param> /// <param name="down">The downwards direction to use for the checks.</param> protected virtual void GeneratePointsIncludingSegments(Vector3 forward, Vector3 down) { GeneratePoints(forward, down); collisionCheckFrequency = Mathf.Clamp(collisionCheckFrequency, 0, segmentCount); int step = segmentCount / (collisionCheckFrequency > 0 ? collisionCheckFrequency : 1); for (int index = 0; index < segmentCount - step; index += step) { Vector3 currentPoint = points[index]; Vector3 nextPoint = index + step < points.Count ? points[index + step] : points[points.Count - 1]; Vector3 nextPointDirection = (nextPoint - currentPoint).normalized; float nextPointDistance = Vector3.Distance(currentPoint, nextPoint); Ray pointsRay = new Ray(currentPoint, nextPointDirection); RaycastHit pointsHitData; if (!PhysicsCast.Raycast(physicsCast, pointsRay, out pointsHitData, nextPointDistance, Physics.IgnoreRaycastLayer)) { continue; } Vector3 collisionPoint = pointsRay.GetPoint(pointsHitData.distance); Ray downwardRay = new Ray(collisionPoint + Vector3.up * 0.01f, Vector3.down); RaycastHit downwardHitData; if (!PhysicsCast.Raycast(physicsCast, downwardRay, out downwardHitData, float.PositiveInfinity, Physics.IgnoreRaycastLayer)) { continue; } TargetHit = downwardHitData; Vector3 newDownPosition = downwardRay.GetPoint(downwardHitData.distance); Vector3 newJointPosition = newDownPosition.y < forward.y ? new Vector3(newDownPosition.x, forward.y, newDownPosition.z) : forward; GeneratePoints(newJointPosition, newDownPosition); break; } ResultsChanged?.Invoke(eventData.Set(TargetHit, Points)); }
/// <summary> /// Projects a straight line downwards from the provided point. /// </summary> /// <param name="downwardOrigin">The origin of the projected line.</param> /// <returns>The collision point or the point being the furthest away on the cast line if nothing is hit.</returns> protected virtual Vector3 ProjectDown(Vector3 downwardOrigin) { Vector3 point = Vector3.zero; Ray ray = new Ray(downwardOrigin, Vector3.down); RaycastHit hitData; bool downRayHit = PhysicsCast.Raycast(physicsCast, ray, out hitData, maximumLength.y, Physics.IgnoreRaycastLayer); if (!downRayHit || (TargetHit?.collider != null && TargetHit.Value.collider != hitData.collider)) { TargetHit = null; point = ray.GetPoint(0f); } if (downRayHit) { point = ray.GetPoint(hitData.distance); TargetHit = hitData; } return(point); }
/// <summary> /// Projects a straight line forward from the current origin. /// </summary> /// <returns>The collision point or the point being the furthest away on the cast line if nothing is hit.</returns> protected virtual Vector3 ProjectForward() { float rotation = Vector3.Dot(Vector3.up, origin.transform.forward.normalized); float length = maximumLength.x; if ((rotation * 100f) > heightLimitAngle) { float controllerRotationOffset = 1f - (rotation - heightLimitAngle / 100f); length = maximumLength.x * controllerRotationOffset * controllerRotationOffset; } Ray ray = new Ray(origin.transform.position, origin.transform.forward); RaycastHit hitData; bool hasCollided = PhysicsCast.Raycast(physicsCast, ray, out hitData, length, Physics.IgnoreRaycastLayer); // Adjust the cast length if something is blocking it. if (hasCollided && hitData.distance < length) { length = hitData.distance; } // Use an offset to move the point back and up a bit to prevent the cast clipping at the collision point. return(ray.GetPoint(length - ADJUSTMENT_OFFSET) + (Vector3.up * ADJUSTMENT_OFFSET)); }