示例#1
0
        public static PathComponent[] ParsePath(string path, Type entityType)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                throw new JsonPatchParseException("Path may not be empty.");
            }

            // Normalize the path by ensuring it begins with a single forward slash, and has
            // no trailing slashes. Modify the path variable itself so that any character
            // positions we report in error messages are accurate.
            path = "/" + path.Trim('/');

            // Keep track of our current position in the path string (for error reporting).
            int pos = 1;

            var pathComponents   = path.Split('/').Skip(1).ToArray();
            var parsedComponents = new PathComponent[pathComponents.Length];

            for (int i = 0; i < pathComponents.Length; i++)
            {
                var pathComponent = pathComponents[i];

                try
                {
                    parsedComponents[i] = ParsePathComponent(pathComponent, entityType,
                                                             i > 0 ? parsedComponents[i - 1] : null);
                }
                catch (JsonPatchParseException e)
                {
                    throw new JsonPatchParseException(string.Format(
                                                          "The path \"{0}\" is not valid: {1}\n" +
                                                          "(Error occurred while parsing path component \"{2}\" at character position {3}.)",
                                                          path, e.Message, pathComponent, pos), e);
                }

                pos += pathComponent.Length + 1;
            }

            return(parsedComponents);
        }
示例#2
0
 private void Blowing()
 {
     m_Timer -= Time.deltaTime;
     DontWiggle();
     if (m_Timer < 0)
     {
         m_State = State.GoingOut;
         PathComponent pathComponent = GetComponent <PathComponent>();
         if (pathComponent != null)
         {
             pathComponent.ClearPath();
             pathComponent.AddPathPoint(OutPoint);
             pathComponent.FollowPath         = true;
             pathComponent.PathCompleteAction = () =>
             {
                 m_State = State.Waiting;
                 pathComponent.FollowPath = false;
                 m_Timer = UnityEngine.Random.Range(MinWaitTime, MaxWaitTime);
             };
         }
     }
 }
    /// <summary>
    /// Creates a path component from a start point and end point.
    /// </summary>
    /// <returns>A new path component from the specified start and end points.</returns>
    /// <param name="startInput">The start point of the path component.</param>
    /// <param name="endInput">The end point of the path component.</param>
    private PathComponent CreatePath(PathInput startInput, PathInput endInput)
    {
        Vector3 start  = startInput.position;
        Vector3 end    = endInput.position;
        Vector3 center = (start + end) / 2;

        Vector3 lookVector = end - start;

        if (lookVector == Vector3.zero)
        {
            lookVector = Vector3.forward;
        }
        PathComponent path = Instantiate(pathPrefab, center, Quaternion.LookRotation(lookVector, Vector3.up)) as PathComponent;

        path.SetPath(start, end);
        path.transform.Rotate(new Vector3(0, -90, 0));
        Vector3 tempScale = path.transform.localScale;

        tempScale.x *= Vector3.Magnitude(end - start);
        path.transform.localScale = tempScale;
        return(path);
    }
示例#4
0
    /// <summary>
    /// Finds the closest path to the object and assigns its path position accordingly.
    /// </summary>
    /// <param name="position">The position of the object.</param>
    /// <param name="pathMovement">The path movement component of the object.</param>
    public static void FindClosestPath(Vector3 position, PathMovement pathMovement)
    {
        PathComponent closestPath = null;
        float         minDistance = (float)Int32.MaxValue;

        foreach (PathComponent pathComponent in LevelManager.Instance.fullPath)
        {
            float pathDistance = DistancePointLine(RemoveY(position), RemoveY(pathComponent.Start), RemoveY(pathComponent.End));
            if (pathDistance < minDistance)
            {
                minDistance = pathDistance;
                closestPath = pathComponent;
                if (minDistance < 0.05f)
                {
                    break;
                }
            }
        }
        pathMovement.currentPath  = closestPath;
        pathMovement.startPath    = closestPath;
        pathMovement.pathProgress = ProjectionPointLine(position, closestPath.Start, closestPath.End).x / closestPath.Length.x;
    }
示例#5
0
    private static string RemoveOtherMakeAndCygwinFromPath(string WindowsPath)
    {
        string[] PathComponents = WindowsPath.Split(';');
        string   NewPath        = "";

        foreach (string PathComponent in PathComponents)
        {
            // Everything that contains /bin or /sbin is suspicious, check if it has make in it
            if (PathComponent.Contains("\\bin") || PathComponent.Contains("/bin") || PathComponent.Contains("\\sbin") || PathComponent.Contains("/sbin"))
            {
                if (File.Exists(PathComponent + "/make.exe") || File.Exists(PathComponent + "make.exe") || File.Exists(PathComponent + "/cygwin1.dll"))
                {
                    LogInformation("Removing {0} from PATH since it contains possibly colliding make.exe", PathComponent);
                    continue;
                }
            }

            NewPath = NewPath + ';' + PathComponent + ';';
        }

        return(NewPath);
    }
示例#6
0
    /// <summary>
    /// Gets the distance from the player to the back of the line, following the path.
    /// </summary>
    /// <returns>The distance from the player to the back of the line, following the path.</returns>
    /// <param name="player">The player to get a distance from.</param>
    public float GetBackDistance(Player player)
    {
        PathComponent currentPath     = pathComponent;
        PathComponent targetPath      = player.GetCurrentPath();
        float         currentDistance = 0;

        if (currentPath != targetPath)
        {
            currentDistance += PathUtil.DistanceXZ(lineStart, currentPath.Start);
            currentPath      = currentPath.previousPath;
            while (currentPath != null && currentPath != targetPath)
            {
                currentDistance += currentPath.Magnitude;
                currentPath      = currentPath.previousPath;
            }
            currentDistance += PathUtil.DistanceXZ(currentPath.End, player.transform.position);
        }
        else
        {
            currentDistance = PathUtil.DistanceXZ(lineStart, player.transform.position);
        }
        return(currentDistance);
    }
示例#7
0
 private void Waiting()
 {
     m_Timer -= Time.deltaTime;
     DontWiggle();
     if (m_Timer < 0)
     {
         m_State = State.GoingIn;
         PathComponent pathComponent = GetComponent <PathComponent>();
         if (pathComponent != null)
         {
             pathComponent.ClearPath();
             pathComponent.AddPathPoint(InPoint);
             pathComponent.FollowPath         = true;
             pathComponent.PathCompleteAction = () =>
             {
                 m_State = State.Blowing;
                 Instantiate(WolfBreathPrefab, new Vector3(transform.position.x + SpawnBreathOffset, 2.75f, transform.position.z), Quaternion.identity);
                 pathComponent.FollowPath = false;
                 m_Timer = BlowTime;
             };
         }
     }
 }
示例#8
0
    private void Attacking(GameObject facingTower)
    {
        if (m_Graphics != null)
        {
            m_Graphics.transform.rotation = Quaternion.Slerp(m_Graphics.transform.rotation, Quaternion.identity, 3.0f * Time.deltaTime);
        }

        m_AttackTimer -= Time.deltaTime;
        if (m_AttackTimer < 0)
        {
            if (facingTower != null)
            {
                m_AttackTimer = AttackTime;
                DamageComponent damageComponent = facingTower.GetComponent <DamageComponent>();
                if (damageComponent != null)
                {
                    damageComponent.TakeDamage(AttackDamage, gameObject, DamageType.Mob);
                }
            }
        }

        if (facingTower == null)
        {
            m_State = State.Moving;
            PathComponent pathComponent = GetComponent <PathComponent>();
            if (pathComponent != null)
            {
                pathComponent.FollowPath = true;
            }
            Rigidbody rigidBody = GetComponent <Rigidbody>();
            if (rigidBody != null)
            {
                rigidBody.isKinematic = false;
            }
        }
    }
示例#9
0
    private void Spawning()
    {
        m_SpawnTimer -= Time.deltaTime;

        Rigidbody rigidbody = GetComponent <Rigidbody>();

        if (rigidbody != null)
        {
            rigidbody.MovePosition(Vector3.Lerp(m_End, m_Start, m_SpawnTimer / SpawnTime));
        }

        if (m_SpawnTimer < 0)
        {
            m_State            = State.Moving;
            transform.position = m_End;
            if (rigidbody != null)
            {
                rigidbody.position = m_End;
            }
            PathComponent pathComponent = GetComponent <PathComponent>();
            if (pathComponent != null)
            {
                pathComponent.FollowPath = true;
            }
            DamageComponent damageComponent = GetComponent <DamageComponent>();
            if (damageComponent != null)
            {
                damageComponent.enabled = true;
            }
            BoxCollider[] colliders = GetComponentsInChildren <BoxCollider>();
            foreach (BoxCollider collider in colliders)
            {
                collider.enabled = true;
            }
        }
    }
示例#10
0
 protected static UrlPattern <P1, P2, P3, P4> Path <P1, P2, P3, P4>(string pattern, PathComponent <P1> p1, PathComponent <P2> p2, PathComponent <P3> p3, UrlArgument <P4> p4)
 {
     return(new UrlPattern <P1, P2, P3, P4>(pattern, p1, p2, p3, p4));
 }
示例#11
0
 protected static UrlPattern <P1, P2> Path <P1, P2>(string pattern, PathComponent <P1> p1, UrlArgument <P2> p2)
 {
     return(new UrlPattern <P1, P2>(pattern, p1, p2));
 }
示例#12
0
 public void PathComponentHashCodeWorks2() {
   var p1 = new PathComponent("foo", 0, 3, PathComparisonOption.CaseSensitive);
   var p2 = new PathComponent("Foo", 0, 3, PathComparisonOption.CaseSensitive);
   Assert.AreNotEqual(p1.GetHashCode(), p2.GetHashCode());
 }
示例#13
0
 public void PathComponentEqualityWorks2() {
   var p1 = new PathComponent("foo", 0, 3, PathComparisonOption.CaseSensitive);
   var p2 = new PathComponent("Foo", 0, 3, PathComparisonOption.CaseSensitive);
   Assert.AreNotEqual(p1, p2);
 }
 public static NullableRefComponent <T> OrNull <T>(this PathComponent <T> b, string nullValueString)
     where T : class
 {
     return(new NullableRefComponent <T>(b, nullValueString));
 }
 public NullableValueComponent(PathComponent <T> basis, string nullValueString = "")
     : base(basis, nullValueString, (T?)null)
 {
 }
示例#16
0
 public QueryArg(string name, PathComponent <T> type)
     : base(type.RegexString)
 {
     this.name = name;
     this.type = type;
 }
示例#17
0
 protected static QueryArg <T> Arg <T>(string name, PathComponent <T> type)
 {
     return(new QueryArg <T>(name, type));
 }
示例#18
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);
    }
示例#19
0
        public object GetValueFromPath(Type entityType, PathComponent[] pathComponents, object entity)
        {
            try
            {
                if (entity == null)
                {
                    throw new JsonPatchException("The root object is null.");
                }

                object previous = entity;

                for (int i = 0; i < pathComponents.Length; i++)
                {
                    string parentPath    = PathComponent.GetFullPath(pathComponents.Take(i));
                    var    pathComponent = pathComponents[i];

                    TypeSwitch.On(pathComponent)
                    .Case((PropertyPathComponent component) =>
                    {
                        if (previous == null)
                        {
                            throw new JsonPatchException(string.Format(
                                                             "Cannot get property \"{0}\" from null object at path \"{1}\".",
                                                             component.Name, parentPath));
                        }

                        previous = component.GetPropertyInfo(previous).GetValue(previous);
                    })
                    .Case((DictionaryPathComponent component) =>
                    {
                        try
                        {
                            var dictionary = (IDictionary)previous;
                            previous       = dictionary[component.Key];
                        }
                        catch (Exception e)
                        {
                            throw new JsonPatchException(string.Format(
                                                             "Cannot access object by key {0} from dictionary at path \"{1}\".",
                                                             component.Key, parentPath), e);
                        }
                    })
                    .Case((CollectionIndexPathComponent component) =>
                    {
                        try
                        {
                            var list = (IList)previous;
                            previous = list[component.CollectionIndex];
                        }
                        catch (Exception e)
                        {
                            throw new JsonPatchException(string.Format(
                                                             "Cannot access index {0} from collection at path \"{1}\".",
                                                             component.CollectionIndex, parentPath), e);
                        }
                    });
                }

                return(previous);
            }
            catch (Exception e)
            {
                throw new JsonPatchException(string.Format(
                                                 "Failed to get value from path \"{0}\": {1}",
                                                 PathComponent.GetFullPath(pathComponents), e.Message), e);
            }
        }
示例#20
0
 public WalkerEntity(PathComponent pathComponent)
 {
     Component = new WalkerComponent(pathComponent);
 }
示例#21
0
 /// <inheritdoc/>
 public bool HasComponents(PathComponent components)
 {
     return(PurePath.HasComponents(components));
 }
示例#22
0
        public void SetValueFromPath(Type entityType, PathComponent[] pathComponents, object entity, object value, JsonPatchOperationType operationType)
        {
            try
            {
                PathComponent[] parent     = pathComponents.Take(pathComponents.Length - 1).ToArray();
                string          parentPath = PathComponent.GetFullPath(parent);

                object previous = GetValueFromPath(entityType, parent, entity);

                if (previous == null)
                {
                    throw new JsonPatchException(string.Format("Value at parent path \"{0}\" is null.", parentPath));
                }

                var target = pathComponents.Last();

                TypeSwitch.On(target)
                .Case((PropertyPathComponent component) =>
                {
                    switch (operationType)
                    {
                    case JsonPatchOperationType.add:
                    case JsonPatchOperationType.replace:
                        component.GetPropertyInfo(previous).SetValue(previous, ConvertValue(value, component.ComponentType));
                        break;

                    case JsonPatchOperationType.remove:
                        component.GetPropertyInfo(previous).SetValue(previous, null);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("operationType");
                    }
                })
                .Case((CollectionPathComponent component) =>
                {
                    var list = previous as IList;
                    if (list == null)
                    {
                        throw new JsonPatchException(string.Format("Value at parent path \"{0}\" is not a valid collection.", parentPath));
                    }

                    switch (operationType)
                    {
                    case JsonPatchOperationType.add:
                        list.Add(ConvertValue(value, component.ComponentType));
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("operationType");
                    }
                })
                .Case((CollectionPathComponent component) =>
                {
                    var list = previous as IList;
                    if (list == null)
                    {
                        throw new JsonPatchException(string.Format("Value at parent path \"{0}\" is not a valid collection.", parentPath));
                    }

                    switch (operationType)
                    {
                    case JsonPatchOperationType.add:
                        list.Add(ConvertValue(value, component.ComponentType));
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("operationType");
                    }
                })
                .Case((CollectionIndexPathComponent component) =>
                {
                    var list = previous as IList;
                    if (list == null)
                    {
                        throw new JsonPatchException(string.Format("Value at parent path \"{0}\" is not a valid collection.", parentPath));
                    }

                    switch (operationType)
                    {
                    case JsonPatchOperationType.add:
                        list.Insert(component.CollectionIndex, ConvertValue(value, component.ComponentType));
                        break;

                    case JsonPatchOperationType.remove:
                        list.RemoveAt(component.CollectionIndex);
                        break;

                    case JsonPatchOperationType.replace:
                        list[component.CollectionIndex] = ConvertValue(value, component.ComponentType);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("operationType");
                    }
                });
            }
            catch (Exception e)
            {
                throw new JsonPatchException(string.Format(
                                                 "Failed to set value at path \"{0}\" while performing \"{1}\" operation: {2}",
                                                 PathComponent.GetFullPath(pathComponents), operationType, e.Message), e);
            }
        }
示例#23
0
        public PathComponent ParsePathComponent(string component, Type rootEntityType, PathComponent previous = null)
        {
            if (string.IsNullOrWhiteSpace(component))
            {
                throw new JsonPatchParseException("Path component may not be empty.");
            }

            // If the path component is a positive integer, it represents a collection index.
            if (component.IsPositiveInteger())
            {
                if (previous == null)
                {
                    throw new JsonPatchParseException("The first path component may not be a collection index.");
                }

                if (!previous.IsCollection)
                {
                    throw new JsonPatchParseException(string.Format(
                                                          "Collection index (\"{0}\") is not valid here because the previous path component (\"{1}\") " +
                                                          "does not represent a collection type.",
                                                          component, previous.Name));
                }

                return(new CollectionIndexPathComponent(component)
                {
                    CollectionIndex = component.ToInt32(),
                    ComponentType = GetCollectionType(previous.ComponentType)
                });
            }

            // If the path component is a '-' character, it represents insert of an element at the end of a collection
            if (component.Equals("-", StringComparison.InvariantCultureIgnoreCase))
            {
                if (previous == null)
                {
                    throw new JsonPatchParseException("The first path component may not be a '-'.");
                }

                if (!previous.IsCollection)
                {
                    throw new JsonPatchParseException(string.Format(
                                                          "Character '-' is not valid here because the previous path component (\"{1}\") " +
                                                          "does not represent a collection type.",
                                                          component, previous.Name));
                }

                return(new CollectionPathComponent(component)
                {
                    ComponentType = GetCollectionType(previous.ComponentType)
                });
            }

            // Otherwise, the path component represents a property name.

            // Attempt to retrieve the corresponding property.
            Type parentType = (previous == null) ? rootEntityType : previous.ComponentType;
            var  property   = GetProperty(parentType, component);

            if (property == null)
            {
                throw new JsonPatchParseException(string.Format("There is no property named \"{0}\" on type {1}.",
                                                                component, parentType.Name));
            }

            return(new PropertyPathComponent(property.Name)
            {
                ComponentType = property.PropertyType
            });
        }
示例#24
0
        private static PathComponent ParsePathComponent(string component, Type rootEntityType, PathComponent previous = null)
        {
            if (string.IsNullOrWhiteSpace(component))
            {
                throw new JsonPatchParseException("Path component may not be empty.");
            }

            // If the path component is a positive integer, it represents a collection index.
            if (component.IsPositiveInteger())
            {
                if (previous == null)
                {
                    throw new JsonPatchParseException("The first path component may not be a collection index.");
                }

                if (!previous.IsCollection)
                {
                    throw new JsonPatchParseException(string.Format(
                                                          "Collection index (\"{0}\") is not valid here because the previous path component (\"{1}\") " +
                                                          "does not represent a collection type.",
                                                          component, previous.Name));
                }

                return(new CollectionIndexPathComponent(component)
                {
                    CollectionIndex = component.ToInt32(),
                    ComponentType = GetCollectionType(previous.ComponentType)
                });
            }

            // Otherwise, the path component represents a property name.

            // Attempt to retrieve the corresponding property.
            Type parentType = (previous == null) ? rootEntityType : previous.ComponentType;
            var  property   = parentType.GetProperty(component);

            if (property == null)
            {
                throw new JsonPatchParseException(string.Format("There is no property named \"{0}\" on type {1}.",
                                                                component, parentType.Name));
            }

            return(new PropertyPathComponent(component)
            {
                PropertyInfo = property,
                ComponentType = property.PropertyType
            });
        }
 public static NullableValueComponent <T> Or <T>(this PathComponent <T> b, string nullValueString)
     where T : struct
 {
     return(new NullableValueComponent <T>(b, nullValueString));
 }
示例#26
0
 /// <inheritdoc/>
 public string GetComponents(PathComponent components)
 {
     return(PurePath.GetComponents(components));
 }
示例#27
0
 /// <summary>
 /// Creates a new path renderer list.
 /// </summary>
 /// <param name="startPath">The start of the path being rendered.</param>
 public PathRendererList(PathComponent startPath)
 {
     pathList    = new Deque <PathRenderer>();
     outlinePath = LevelManager.Instance.outlinePath;
     Init(startPath);
 }
    /// <summary>
    /// Creates a level from the given input.
    /// </summary>
    /// <param name="pathInput">The path for the level.</param>
    /// <param name="enemyInput">Enemies in the level.</param>
    /// <param name="collectibleInput">Collectibles in the level.</param>
    /// <param name="blockInput">Blocks in the level.</param>
    public void CreateLevel(List <PathInput> pathInput, List <EnemyInput> enemyInput, List <CollectibleInput> collectibleInput, List <BlockInput> blockInput)
    {
        LevelManager levelManager = LevelManager.Instance;

        // Construct the path from the input points.
        List <PathComponent> fullPath = new List <PathComponent>(pathInput.Count - 1);

        // Construct virtual platforms to represent the colliders.
        for (int i = 0; i < fullPath.Capacity; i++)
        {
            if (pathInput[i].type != PlatformType.Gap || i == 0)
            {
                List <Vector3> platform      = new List <Vector3>();
                Vector3        direction     = pathInput[i + 1].position - pathInput[i].position;
                Vector3        flatDirection = PathUtil.RemoveY(direction);
                float          thickness     = pathInput[i].type == PlatformType.Surface ? surfaceThickness : platformThickness;
                if (flatDirection == Vector3.zero)
                {
                    // Wall.
                    if (i > 0)
                    {
                        flatDirection = Vector3.Normalize(PathUtil.RemoveY(pathInput[i].position - pathInput[i - 1].position)) * thickness;
                        Vector3 directionRotate = new Vector3(flatDirection.z, 0, -flatDirection.x);
                        Vector3 top             = pathInput[i + 1].position.y > pathInput[i].position.y ? pathInput[i + 1].position : pathInput[i].position;
                        platform.Add(top + directionRotate);
                        platform.Add(top + directionRotate + flatDirection);
                        platform.Add(top - directionRotate + flatDirection);
                        platform.Add(top - directionRotate);
                        CreatePlatform(new PlatformInput(platform, pathInput[i].type), Mathf.Abs(pathInput[i + 1].position.y - pathInput[i].position.y));
                    }
                }
                else
                {
                    Vector3 flatDirectionNorm = Vector3.Normalize(flatDirection);
                    Vector3 directionRotate   = new Vector3(flatDirectionNorm.z, 0, -flatDirectionNorm.x) * thickness;
                    platform.Add(pathInput[i + 1].position + directionRotate);
                    platform.Add(pathInput[i + 1].position - directionRotate);
                    platform.Add(pathInput[i].position - directionRotate);
                    platform.Add(pathInput[i].position + directionRotate);
                    CreatePlatform(new PlatformInput(platform, pathInput[i].type));
                }
            }
        }

        for (int i = 0; i < fullPath.Capacity; i++)
        {
            // Make and position the path component.
            PathComponent pathComponent = CreatePath(pathInput[i], pathInput[i + 1]);
            fullPath.Add(pathComponent);
            pathComponent.lineMaterial = lineMaterial;

            // Link paths together.
            if (i > 0)
            {
                pathComponent.previousPath = fullPath[i - 1];
                fullPath[i - 1].nextPath   = pathComponent;
            }

            pathComponent.Init();
        }

        if (fullPath.Count == 0)
        {
            print("Invalid path.");
            return;
        }

        GetComponent <Visibility>().ApplySetting();

        // Set the player on a path.
        Player       player         = Instantiate(playerPrefab) as Player;
        PathMovement playerMovement = player.GetComponent <PathMovement>();

        playerMovement.currentPath = fullPath[0];
        playerMovement.startPath   = fullPath[0];
        foreach (PathComponent pathComponent in fullPath)
        {
            pathComponent.transform.parent = player.transform;
        }

        levelManager.GetComponent <CameraSetting>().InitializeCameras(player);
        levelManager.player = player;

        // Create the goal at the end of the path.
        Goal goal = Instantiate(goalPrefab);

        goal.transform.parent = levelManager.transform.FindChild("Platforms").transform;
        Vector3    pathEnd = PathUtil.SetY(fullPath[fullPath.Count - 1].End, PathUtil.ceilingHeight);
        RaycastHit hit;

        if (Physics.Raycast(pathEnd, Vector3.down, out hit, PathUtil.ceilingHeight * 1.1f))
        {
            goal.transform.position = hit.point + Vector3.up * 0.025f;
        }
        else
        {
            goal.transform.position = fullPath[fullPath.Count - 1].End;
        }
        levelManager.goal = goal;

        // Create enemies from the input.
        List <Enemy> enemies = new List <Enemy>(enemyInput.Count);

        foreach (EnemyInput input in enemyInput)
        {
            if (input.enemyIndex < enemyPrefabs.Length)
            {
                Enemy enemy = Instantiate(enemyPrefabs[input.enemyIndex]) as Enemy;
                enemies.Add(enemy);
                enemy.transform.parent = levelManager.transform.FindChild("Enemies").transform;
                if (enemy.GetComponent <PathMovement>())
                {
                    // Create the enemy path.
                    int pathLength = input.path.Count - 1;
                    List <PathComponent> enemyPath = new List <PathComponent>(pathLength);
                    for (int i = 0; i < pathLength; i++)
                    {
                        PathComponent pathComponent = CreatePath(input.path[i], input.path[i + 1]);
                        enemyPath.Add(pathComponent);
                        if (i > 0)
                        {
                            pathComponent.previousPath = enemyPath[i - 1];
                            enemyPath[i - 1].nextPath  = pathComponent;
                        }
                        pathComponent.transform.parent = enemy.transform;
                    }
                    // Allow enemy paths to be circular.
                    if (input.path[0].Equals(input.path[input.path.Count - 1]))
                    {
                        enemyPath[0].previousPath          = enemyPath[pathLength - 1];
                        enemyPath[pathLength - 1].nextPath = enemyPath[0];
                    }
                    enemy.GetComponent <PathMovement>().currentPath = enemyPath[0];
                    enemy.GetComponent <PathMovement>().startPath   = enemyPath[0];
                }
                else
                {
                    enemy.transform.position = input.path[0].position;
                }
                // Make sure the enemy is above ground.
                Collider enemyCollider = null;
                foreach (Collider collider in enemy.GetComponents <Collider>())
                {
                    if (!collider.isTrigger)
                    {
                        enemyCollider = collider;
                        break;
                    }
                }
                float offset = enemyCollider.bounds.extents.y;
                Physics.Raycast(enemy.transform.position + Vector3.up * offset, Vector3.down, out hit, offset);
                enemy.transform.position = hit.point + Vector3.up * offset / 2;
            }
        }

        // Create collectibles from the input.
        List <Item> items = new List <Item>(collectibleInput.Count);

        foreach (CollectibleInput input in collectibleInput)
        {
            Item item = null;
            if (input.type == "coin")
            {
                item = Instantiate(itemPrefabs[(int)Items.Coin]) as Item;
            }
            else if (input.type == "power_up_size")
            {
                item = Instantiate(itemPrefabs[(int)Items.Mushroom]) as Item;
            }
            else if (input.type == "power_up_speed")
            {
                item = Instantiate(itemPrefabs[(int)Items.Coffee]) as Item;
            }
            else if (input.type == "power_up_range")
            {
                item = Instantiate(itemPrefabs[(int)Items.Toothpick]) as Item;
            }
            else if (input.type == "power_up_melee")
            {
                item = Instantiate(itemPrefabs[(int)Items.FlySwatter]) as Item;
            }

            if (item != null)
            {
                item.transform.parent   = levelManager.transform.FindChild("Items").transform;
                item.transform.position = input.position;
                item.SetInitPosition(input.position);
            }
        }

        // Create blocks from the input.
        List <Block> blocks = new List <Block>(blockInput.Count);

        foreach (BlockInput input in blockInput)
        {
            Block block = Instantiate(blockPrefabs[input.blockIndex]) as Block;
            if (input.contentIndex != -1)
            {
                block.contents = itemPrefabs[input.contentIndex];
            }
            block.transform.parent   = levelManager.transform.FindChild("Blocks").transform;
            block.transform.position = input.position;
            blocks.Add(block);
        }

        // Pass the needed data to the level manager to store.
        levelManager.fullPath = fullPath;
        levelManager.InitializePathRenderer();
        levelManager.enemies   = enemies;
        levelManager.items     = items;
        levelManager.blocks    = blocks;
        LevelManager.numDeaths = 0;
    }