/// <summary> /// Moves the object along the ribbon path. /// </summary> /// <returns>Whether the object was able to move.</returns> /// <param name="forward">Whether to move the object forward along the path.</param> public bool MoveAlongPath(bool forward) { float moveDistance = moveSpeed; // Check for side collision. Vector3 sidePosition = transform.position + Vector3.down * (groundOffset - COLLISIONOFFSET) + GetRotatedSideOffset(forward); float sideIncrement = groundOffset * 2 / NUMSIDECHECKS + 2 * COLLISIONOFFSET; RaycastHit hit; int loopStart = 1; // Test for sloped ground. if (Physics.Raycast(sidePosition, currentPath.GetDirection(forward), out hit, moveSpeed + COLLISIONOFFSET, collisionLayers)) { float groundDistance = hit.distance; sidePosition.y += sideIncrement; loopStart++; if (Physics.Raycast(sidePosition, currentPath.GetDirection(forward), out hit, moveSpeed + COLLISIONOFFSET, collisionLayers)) { if (hit.distance <= groundDistance || Mathf.Atan(sideIncrement / (hit.distance - groundDistance)) > MAXSLOPEANGLE * Mathf.Deg2Rad) { return(false); } } } // Test the rest of the vertical distance for blockage. for (int i = loopStart; i < NUMSIDECHECKS; i++) { if (Physics.Raycast(sidePosition, currentPath.GetDirection(forward), out hit, moveSpeed + COLLISIONOFFSET, collisionLayers)) { moveDistance = Mathf.Min(moveDistance, hit.distance - COLLISIONOFFSET); if (moveDistance < Mathf.Epsilon) { return(false); } } sidePosition.y += sideIncrement; } pathProgress = currentPath.IncrementPathProgress(pathProgress, moveDistance, forward); // Check if the object has moved past the path's bounds. // Switch to the next/previous path if so. while (pathProgress > 1) { if (currentPath.nextPath == null) { pathProgress = 1; return(false); } else { float overflow = currentPath.GetMagnitudeFromProgress(pathProgress - 1); currentPath = currentPath.nextPath; pathProgress = currentPath.GetProgressFromMagnitude(overflow); } } while (pathProgress < 0) { if (currentPath.previousPath == null) { pathProgress = 0; return(false); } else { float underflow = currentPath.GetMagnitudeFromProgress(-pathProgress); currentPath = currentPath.previousPath; pathProgress = currentPath.GetProgressFromMagnitude(currentPath.Magnitude - underflow); } } // Move the object. PathUtil.SetXZ(transform, currentPath.GetPositionInPath(pathProgress)); Vector3 sideCenter = transform.position + GetRotatedSideOffset(forward); if (Physics.Raycast(sideCenter, Vector3.down, out hit, groundOffset, collisionLayers)) { PathUtil.SetY(transform, hit.point.y + groundOffset); } // Rotate the object to face forward. if (!rotates) { FacePath(forward); } return(true); }