示例#1
0
    /// <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);
    }