Example #1
0
    /* static */
    public void AddNodeToOpenList(MovePointBehavior theNode, float costFromPreviousObject, 
		MovePointBehavior previousNode)
    {
        float costSoFar = costFromPreviousObject;
        if (previousNode != null)
        {
            costSoFar += previousNode.costSoFar;
        }
        theNode.costSoFar = costSoFar;
        theNode.previousPathNode = previousNode;
        openList.Add(theNode);
    }
Example #2
0
	/// <summary>
	/// The update function is to catch input and to do the movement of the agent, this is temporary code. for testing purposes only. 
    /// 
    /// Alex Reiss
	/// </summary>

	void Update () 
    {
        if (!currentlyMoving && canMove)
        {
			if (pathList == null)
				pathList = new List<MovePointBehavior>();

            if (pathList.Count > 0)
            {
                for (int index = 0; index < currentMovePoint.neighborList.Length; index++)
                {
                    if (currentMovePoint.neighborList[index] == pathList[0])
                    {
                        pointToMoveTo = currentMovePoint.neighborList[index];
                        currentlyMoving = true;
                        AudioBehavior.isMoving = true;
                        currentMovementTime = timeToMoveToPoint;
                    }
                }
            }
        }
        else if(canMove)
        {

            if (currentMovementTime < 0.0f)
            {
                currentMovePoint = pointToMoveTo;
                currentMovementTime = 0.0f;
                transform.position = currentMovePoint.transform.position;
                currentlyMoving = false;
                AudioBehavior.isMoving = false;
                pointToMoveTo = null;
                pathList.RemoveAt(0);
            }
            else
            {
                float forTForLerp = (timeToMoveToPoint - currentMovementTime) / timeToMoveToPoint;
                float forTheChangeInZ = Mathf.Lerp(currentMovePoint.transform.position.z, pointToMoveTo.transform.position.z, forTForLerp);
                float forTheChangeInX = Mathf.Lerp(currentMovePoint.transform.position.x, pointToMoveTo.transform.position.x, forTForLerp);
                transform.position = new Vector3(forTheChangeInX, transform.position.y, forTheChangeInZ);
                currentMovementTime -= Time.deltaTime;
            }
        }
		
		if (pathList.Count == 0)
			canMove = false;
	}
    /// <summary>
    /// Iterates over the Player & Enemy nodes to determine if the specified node is occupied.
    /// </summary>
    /// <param name="node"></param>
    /// <returns></returns>
    public ActorBehavior GetActorOnNode(MovePointBehavior node)
    {
        foreach (ActorBehavior squad in playerTeam)
            if (squad.currentMovePoint == node)
                return squad;

        foreach (ActorBehavior squad in enemyTeam)
            if (squad.currentMovePoint == node)
                return squad;

        foreach (ActorBehavior squad in nuetrals)
            if (squad.currentMovePoint == node)
                return squad;

        return null;
    }
Example #4
0
    /// <summary>
    /// Determines the target for this squad.
    /// </summary>
    /// <returns>AI state the controller should enter after determining the target.</returns>
    public override AIState DetermineMovePoint()
    {
        targetActor = null;

        MovePointBehavior movePoint = Actor.currentMovePoint;

        // Get a list of spaces that are within attack range (movement + range).
        CombatSquadBehavior combatSquad = Actor.GetComponent <CombatSquadBehavior>();

        if (combatSquad == null)
        {
            Debug.LogError(string.Format("AI Squad ({0}) does not have a CombatSquadBehavior!", Actor.transform.name));
            Actor.actorHasMovedThisTurn = true;

            return(AIState.PickingSquad);
        }

        int attackRange  = combatSquad.Squad.Range;
        int moveDistance = combatSquad.Squad.Speed;

        List <MovePointBehavior> pointsInRange = new List <MovePointBehavior>();

        movePoint.BuildGraph(attackRange + moveDistance, 0, grid, ref pointsInRange, true);

        // Find the closest actor in attack range.
        foreach (MovePointBehavior node in pointsInRange)
        {
            ActorBehavior actorOnNode = gameController.GetActorOnNode(node);

            if (actorOnNode == null || (actorOnNode.theSide != GameControllerBehaviour.UnitSide.player))
            {
                continue;
            }

            // If the distance to the target is less than the distance to the selected target, target it instead.
            float distance = Vector3.Distance(Actor.transform.position, actorOnNode.transform.position);
            if (distance < distanceToTarget)
            {
                targetActor      = actorOnNode;
                distanceToTarget = distance;
            }
        }

        // If a target was found, move toward it.
        if (targetActor != null)
        {
            // Build a path to the actor.
            List <MovePointBehavior> pathList = movePoint.FindPath(targetActor.currentMovePoint, (moveDistance + attackRange), grid, true);

            // Remove the target's move point from the grid.
            pathList.RemoveAt(pathList.Count - 1);

            // Determine the excess items in the path list.
            int excess = pathList.Count - moveDistance;

            if (excess > 0)
            {
                pathList.RemoveRange(pathList.Count - excess, excess);
            }

            if (pathList.Count > 0)
            {
                MovePointBehavior targetPoint = pathList[pathList.Count - 1];

                // Determine the fastest path to the target point.
                pathList = movePoint.FindPath(targetPoint, moveDistance, grid);

                if (pathList != null)
                {
                    Actor.pathList = pathList;
                    Actor.canMove  = true;

                    grid.ignoreList.Remove(movePoint);

                    grid.ignoreList.Add(targetPoint);

                    Actor.actorHasMovedThisTurn = true;

                    return(AIState.WaitingForMove);
                }
            }
            else
            {
                Actor.actorHasMovedThisTurn = true;

                return(AIState.WaitingForMove);
            }
        }
        else
        {
            targetActor      = null;
            distanceToTarget = float.PositiveInfinity;

            // No target was found, so determine the closest target to move towards.
            foreach (ActorBehavior playerSquad in gameController.playerTeam)
            {
                float distance = Vector3.Distance(Actor.transform.position, playerSquad.transform.position);
                if (distance < distanceToTarget)
                {
                    targetActor      = playerSquad;
                    distanceToTarget = distance;
                }
            }

            // Retrieve a list of all nodes within movement range.
            List <MovePointBehavior> nodesInRange = new List <MovePointBehavior>();
            movePoint.BuildGraph(moveDistance, 0, grid, ref nodesInRange);

            // Cast a ray to the target and retrieve the farthest one that is in our movement range.
            Ray ray = new Ray(Actor.transform.position, (targetActor.transform.position - Actor.transform.position).normalized);

            // Perform raycasting and store a list of all objects that have been selected.
            List <RaycastHit> hits = new List <RaycastHit>();
            hits.AddRange(Physics.RaycastAll(ray));

            // Iterate over the selection list to determine if the player has clicked on one of her squads.
            foreach (RaycastHit hitInfo in hits.OrderBy(l => l.distance).Reverse())
            {
                MovePointBehavior hitBehavior = hitInfo.transform.GetComponent <MovePointBehavior>();
                if (hitBehavior == null || !nodesInRange.Contains(hitBehavior))
                {
                    continue;
                }

                // Target node has been found! Find a path to it.
                List <MovePointBehavior> pathList = movePoint.FindPath(hitBehavior, moveDistance, grid);

                if (pathList != null)
                {
                    Actor.pathList = pathList;
                    Actor.canMove  = true;

                    grid.ignoreList.Remove(movePoint);
                    grid.ignoreList.Add(hitBehavior);

                    Actor.actorHasMovedThisTurn = true;

                    return(AIState.WaitingForMove);
                }
            }
        }

        Actor.actorHasMovedThisTurn = true;
        return(AIState.PickingSquad);
    }
Example #5
0
 /// <summary>
 /// The update function is to catch input and to do the movement of the agent, this is temporary code. for testing purposes only. 
 /// </summary>
 void Update()
 {
     if (!currentlyMoving)
     {
         if (pathList.Count > 0)
         {
             if (pathList[0] == currentMovePoint.neighborList[0])
             //if (Input.GetKeyDown(KeyCode.UpArrow) && currentMovePoint.North)
             {
                 pointToMoveTo = currentMovePoint.neighborList[0];
                 currentMovementDirection = DirectionOfMovement.North;
                 currentlyMoving = true;
                 currentMovementTime = timeToMoveToPoint;
             }
             else if (pathList[0] == currentMovePoint.neighborList[2])
             //else if (Input.GetKeyDown(KeyCode.DownArrow) && currentMovePoint.South)
             {
                 pointToMoveTo = currentMovePoint.neighborList[2];
                 currentMovementDirection = DirectionOfMovement.South;
                 currentlyMoving = true;
                 currentMovementTime = timeToMoveToPoint;
             }
             else if (pathList[0] == currentMovePoint.neighborList[3])
             //else if (Input.GetKeyDown(KeyCode.LeftArrow) && currentMovePoint.West)
             {
                 pointToMoveTo = currentMovePoint.neighborList[3];
                 currentMovementDirection = DirectionOfMovement.West;
                 currentlyMoving = true;
                 currentMovementTime = timeToMoveToPoint;
             }
             else if (pathList[0] == currentMovePoint.neighborList[1])
             //else if (Input.GetKeyDown(KeyCode.RightArrow) && currentMovePoint.East)
             {
                 pointToMoveTo = currentMovePoint.neighborList[1];
                 currentMovementDirection = DirectionOfMovement.East;
                 currentlyMoving = true;
                 currentMovementTime = timeToMoveToPoint;
             }
         }
     }
     else
     {
         switch (currentMovementDirection)
         {
             case DirectionOfMovement.North:
                 if (currentMovementTime < 0.0f)
                 {
                     currentMovePoint = pointToMoveTo;
                     currentMovementDirection = DirectionOfMovement.None;
                     currentMovementTime = 0.0f;
                     transform.position = currentMovePoint.transform.position;
                     currentlyMoving = false;
                     pointToMoveTo = null;
                     pathList.RemoveAt(0);
                     if (GridBehavior.preCombat && pathList.Count == 0)
                         theGrid.startCombat();
                 }
                 else
                 {
                     float forTForLerp = (timeToMoveToPoint - currentMovementTime) / timeToMoveToPoint;
                     float forTheChangeInZ = Mathf.Lerp(currentMovePoint.transform.position.z, pointToMoveTo.transform.position.z, forTForLerp);
                     transform.position = new Vector3(transform.position.x, transform.position.y, forTheChangeInZ);
                     currentMovementTime -= Time.deltaTime;
                 }
                 break;
             case DirectionOfMovement.South:
                 if (currentMovementTime < 0.0f)
                 {
                     currentMovePoint = pointToMoveTo;
                     currentMovementDirection = DirectionOfMovement.None;
                     currentMovementTime = 0.0f;
                     transform.position = currentMovePoint.transform.position;
                     currentlyMoving = false;
                     pointToMoveTo = null;
                     pathList.RemoveAt(0);
                     if (GridBehavior.preCombat && pathList.Count == 0)
                         theGrid.startCombat();
                 }
                 else
                 {
                     float forTForLerp = (timeToMoveToPoint - currentMovementTime) / timeToMoveToPoint;
                     float forTheChangeInZ = Mathf.Lerp(currentMovePoint.transform.position.z, pointToMoveTo.transform.position.z, forTForLerp);
                     transform.position = new Vector3(transform.position.x, transform.position.y, forTheChangeInZ);
                     currentMovementTime -= Time.deltaTime;
                 }
                 break;
             case DirectionOfMovement.East:
                 if (currentMovementTime < 0.0f)
                 {
                     currentMovePoint = pointToMoveTo;
                     currentMovementDirection = DirectionOfMovement.None;
                     currentMovementTime = 0.0f;
                     transform.position = currentMovePoint.transform.position;
                     currentlyMoving = false;
                     pointToMoveTo = null;
                     pathList.RemoveAt(0);
                     if (GridBehavior.preCombat && pathList.Count == 0)
                         theGrid.startCombat();
                 }
                 else
                 {
                     float forTForLerp = (timeToMoveToPoint - currentMovementTime) / timeToMoveToPoint;
                     float forTheChangeInX = Mathf.Lerp(currentMovePoint.transform.position.x, pointToMoveTo.transform.position.x, forTForLerp);
                     transform.position = new Vector3(forTheChangeInX, transform.position.y, transform.position.z);
                     currentMovementTime -= Time.deltaTime;
                 }
                 break;
             case DirectionOfMovement.West:
                 if (currentMovementTime < 0.0f)
                 {
                     currentMovePoint = pointToMoveTo;
                     currentMovementDirection = DirectionOfMovement.None;
                     currentMovementTime = 0.0f;
                     transform.position = currentMovePoint.transform.position;
                     currentlyMoving = false;
                     pointToMoveTo = null;
                     pathList.RemoveAt(0);
                     if (GridBehavior.preCombat && pathList.Count == 0)
                         theGrid.startCombat();
                 }
                 else
                 {
                     float forTForLerp = (timeToMoveToPoint - currentMovementTime) / timeToMoveToPoint;
                     float forTheChangeInX = Mathf.Lerp(currentMovePoint.transform.position.x, pointToMoveTo.transform.position.x, forTForLerp);
                     transform.position = new Vector3(forTheChangeInX, transform.position.y, transform.position.z);
                     currentMovementTime -= Time.deltaTime;
                 }
                 break;
         }
     }
 }
	/// <summary>
	/// Performs necessary steps to deselect the current squad.
	/// </summary>
	private void deselectSquad()
	{
		if(selectedSquad != null)
		{
			UnitIdleAnimationBehavior[] idles = selectedSquad.GetComponentsInChildren<UnitIdleAnimationBehavior>();
			foreach(UnitIdleAnimationBehavior idle in idles)
				idle.Active = false;
			
			selectedSquad = null;
		}

		startingPoint = null;
		grid.HideMovePoints();
		validTargets = null;
	}
	/// <summary>
	/// Waits for the left mouse button to be clicked, then performs a raycast to determine if the player has clicked
	/// on one of her own squads.
	/// </summary>
	/// <remarks>
	/// Transitions:
	/// 	Player Clicks Valid Squad -> SelectingMovement
	/// </remarks>
	private void updateSelectingUnit()
	{
		// Wait for the left mouse button to be pressed.
		if(Input.GetMouseButtonDown (0))
		{
			Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

			// Perform raycasting and store a list of all objects that have been selected.
			List<RaycastHit> hits = new List<RaycastHit>();
			hits.AddRange(Physics.RaycastAll (ray));

			// Iterate over the selection list to determine if the player has clicked on one of her squads.
			foreach(RaycastHit hitInfo in hits.OrderBy (l => l.distance))
			{
				// Capture the actor behavior on the hit object.
				ActorBehavior actor = hitInfo.transform.GetComponent<ActorBehavior>();
				if(actor == null)
					continue;

				// Ensure that the unit has not moved and belongs to the player.
				if(!actor.actorHasMovedThisTurn && actor.theSide == inputSide)
				{
					// Mark the actor as selected.
					selectedSquad = actor;
					startingPoint = actor.currentMovePoint;

					// Begin the scripted "Idle" animation.
					UnitIdleAnimationBehavior[] idles = selectedSquad.GetComponentsInChildren<UnitIdleAnimationBehavior>();
					foreach(UnitIdleAnimationBehavior idle in idles)
						idle.Active = true;

					// Enable rendering of valid target movement nodes.
					if(actor.currentMovePoint != null)
						actor.currentMovePoint.HighlightValidNodes(actor, grid);

					// STATE CHANGE: SelectingUnit -> SelectingMovement
					controlState = GridControlState.SelectingMovement;

					break;
				}
			}
		}
	}
Example #8
0
    /// <summary>
    /// Creates the grid. The fenced variable is used to determine fences are required.
    ///
    /// Fences are just a name that makes it easier for the gmae designers, the fences are just a means to remove an edge from the graph visually.
    ///
    /// Alex Reiss
    /// </summary>
    public void CreateGrid()
    {
        for (int _i = (gameObject.transform.childCount - 1); _i >= 0; _i--)
        {
            DestroyImmediate(transform.GetChild(_i).gameObject);
        }


        theMap = new MovePointBehavior[theMapLength * theMapWidth];

        if (isFenced)
        {
            theVerticalFence   = new FenceBehavour[(theMapLength) * theMapWidth];
            theHorizontalFence = new FenceBehavour[theMapLength * (theMapWidth)];
        }

        float xPositionOffset  = -(theMapWidth / 2);
        float yPositionOffset  = -(theMapLength / 2);
        float currentXPosition = 0.0f;
        float currentYPosition = 0.0f;

        for (int x = 0; x < theMapLength; x++)
        {
            currentXPosition = xPositionOffset;
            currentYPosition = yPositionOffset + x;
            for (int z = 0; z < theMapWidth; z++)
            {
                MovePointBehavior newMovePoint = null;
                if ((z + x) % 2 == 0)
                {
                    newMovePoint = (MovePointBehavior)Instantiate(theMovePointPrehab, new Vector3(currentXPosition, 1.0f, currentYPosition), Quaternion.identity);
                }
                else
                {
                    newMovePoint = (MovePointBehavior)Instantiate(theAltMovePointPrehab, new Vector3(currentXPosition, 1.0f, currentYPosition), Quaternion.identity);
                }
                newMovePoint.transform.parent = transform;
                newMovePoint.name             = abc[z].ToString() + x.ToString();
                theMap[z + (x * theMapWidth)] = newMovePoint;


                if (isFenced)
                {
                    if (x < theMapLength - 1)
                    {
                        FenceBehavour newVerticalFence = (FenceBehavour)Instantiate(theFencePointPrehab, new Vector3(currentXPosition, 1.0f, currentYPosition + 0.5f), Quaternion.identity);
                        newVerticalFence.transform.parent       = transform;
                        newVerticalFence.name                   = abc[z].ToString() + x.ToString() + "fence" + abc[z].ToString() + (x + 1).ToString();
                        theVerticalFence[z + (x * theMapWidth)] = newVerticalFence;
                    }

                    if (z < theMapWidth - 1)
                    {
                        FenceBehavour newHorizontalFence = (FenceBehavour)Instantiate(theFencePointPrehab, new Vector3(currentXPosition + 0.5f, 1.0f, currentYPosition), Quaternion.identity);
                        newHorizontalFence.transform.parent       = transform;
                        newHorizontalFence.name                   = abc[z].ToString() + x.ToString() + "fence" + abc[z + 1].ToString() + x.ToString();
                        theHorizontalFence[z + (x * theMapWidth)] = newHorizontalFence;
                    }
                }

                currentXPosition = xPositionOffset + z + 1;
            }
        }
    }
Example #9
0
    /// <summary>
    /// Waits for the left mouse button to be clicked, then performs a raycast to determine if the player has clicked
    /// on a valid movement point.
    /// </summary>
    /// <remarks>
    /// Transitions:
    ///     Player presses Escape key -> SelectingUnit
    ///     Player presses Space key -> SelectingTarget
    ///
    ///     Path to movement point cannot be found -> SelectingUnit
    ///     Player selects a valid movement point -> AwaitingMovement
    /// </remarks>
    private void updateSelectingMovement()
    {
        // Allow the player to press the Escape key to deselect their current unit.
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            deselectSquad();
            controlState = GridControlState.SelectingUnit;
            return;
        }

        // Allow the player to press the Space bar to skip the movement step.
        if (Input.GetKeyDown(KeyCode.Space))
        {
            selectedSquad.actorHasMovedThisTurn = true;
            grid.HideMovePoints();
            controlState = GridControlState.SelectingTarget;
            return;
        }

        // Wait for the left mouse button to be pressed.
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            // Perform raycasting and store a list of all objects that have been selected.
            List <RaycastHit> hits = new List <RaycastHit>();
            hits.AddRange(Physics.RaycastAll(ray));

            // Iterate over the selection list to determine if the player has clicked on a valid movementpoint.
            foreach (RaycastHit hitInfo in hits.OrderBy(l => l.distance))
            {
                // Retrieve the movepoint behavior from the hit target.
                MovePointBehavior movePoint = hitInfo.transform.GetComponent <MovePointBehavior>();
                if (movePoint == null || !movePoint.renderer.enabled)
                {
                    continue;
                }

                // Retrieve the combat squad behavior from the currently-selected squad.
                CombatSquadBehavior combatSquad = selectedSquad.GetComponent <CombatSquadBehavior>();
                if (combatSquad == null)
                {
                    Debug.LogError("Selected a unit with no combat squad attached!");
                }

                // Retrieve the maximum movement distance of the selected squad.
                int distance = (combatSquad == null ? 0 : combatSquad.Squad.Speed);

                // Mark the actor as having moved.
                selectedSquad.actorHasMovedThisTurn = true;

                // Retrieve a path from the starting point to the selected node.
                List <MovePointBehavior> pathList = startingPoint.FindPath(movePoint, distance, grid);
                if (pathList != null)
                {
                    selectedSquad.pathList = pathList;
                    selectedSquad.canMove  = true;

                    // Remove the squad's current movement point from the ignore list.
                    grid.ignoreList.Remove(startingPoint);

                    // Add the squad's target movement point to the ignore list.
                    grid.ignoreList.Add(movePoint);

                    // Hide visible nodes on the grid.
                    grid.HideMovePoints();

                    // Transition into the AwaitingMovement state.
                    controlState = GridControlState.AwaitingMovement;
                }
                else
                {
                    Debug.LogError("No path to target!");

                    // Deselect the current squad, but do not allow it to move again!
                    deselectSquad();

                    // Return to the SelectingUnit state.
                    controlState = GridControlState.SelectingUnit;
                }
            }
        }
    }
Example #10
0
    /// <summary>
    /// Attempts to find a path to the target node.
    /// </summary>
    /// <param name="targetNode">Final node the unit should move to.</param>
    /// <param name="maxDistance">Maximum distnance the unit can move.</param>
    /// <param name="grid">Grid that the pathfinding is occurring on.</param>
    /// <param name="skipIgnoreList">Skips the ignore list when building the initial graph.</param>
    /// <returns></returns>
    public List <MovePointBehavior> FindPath(MovePointBehavior targetNode, int maxDistance, GridBehavior grid, bool skipIgnoreList = false)
    {
        // Build the Dijkstra's Graph
        List <MovePointBehavior> graph  = new List <MovePointBehavior>();
        List <MovePointBehavior> tGraph = new List <MovePointBehavior>();

        BuildGraph(maxDistance, 0, grid, ref graph, skipIgnoreList);

        if (!graph.Contains(targetNode))
        {
            return(null);
        }

        Dictionary <MovePointBehavior, int> distance = new Dictionary <MovePointBehavior, int>();
        Dictionary <MovePointBehavior, MovePointBehavior> previous = new Dictionary <MovePointBehavior, MovePointBehavior>();

        foreach (MovePointBehavior node in graph)
        {
            distance.Add(node, int.MaxValue);
            previous.Add(node, null);

            tGraph.Add(node);
        }

        distance[this] = 0;
        previous[this] = null;

        while (tGraph.Count > 0)
        {
            // Find the item with the smallest distance.
            MovePointBehavior node = tGraph[0];
            for (int _i = 0; _i < tGraph.Count; _i++)
            {
                MovePointBehavior _node = tGraph[_i];

                if (grid.ignoreList.Contains(_node) && !skipIgnoreList)
                {
                    continue;
                }

                if (distance[_node] < distance[node])
                {
                    node = _node;
                    MovePointBehavior tNode = tGraph[0];
                    tGraph[0]  = _node;
                    tGraph[_i] = tNode;
                }
            }

            tGraph.RemoveAt(0);

            if (distance[node] == int.MaxValue)
            {
                break;
            }

            foreach (MovePointBehavior neighbor in node.neighborList)
            {
                if (neighbor == null || (!skipIgnoreList && grid.ignoreList.Contains(neighbor)) || !graph.Contains(neighbor))
                {
                    continue;
                }

                int alt = distance[node] + 1;

                if (alt < distance[neighbor])
                {
                    distance[neighbor] = alt;
                    previous[neighbor] = node;
                }
            }
        }

        List <MovePointBehavior> path = new List <MovePointBehavior>();
        MovePointBehavior        u    = targetNode;

        while (previous[u] != null)
        {
            path.Add(u);
            u = previous[u];
        }

        path.Reverse();

        return(path);
    }
	/// <summary>
	/// Attempts to find a path to the target node.
	/// </summary>
	/// <param name="targetNode">Final node the unit should move to.</param>
	/// <param name="maxDistance">Maximum distnance the unit can move.</param>
	/// <param name="grid">Grid that the pathfinding is occurring on.</param>
	/// <param name="skipIgnoreList">Skips the ignore list when building the initial graph.</param>
	/// <returns></returns>
	public List<MovePointBehavior> FindPath(MovePointBehavior targetNode, int maxDistance, GridBehavior grid, bool skipIgnoreList = false)
	{
		// Build the Dijkstra's Graph
		List<MovePointBehavior> graph = new List<MovePointBehavior>();
		List<MovePointBehavior> tGraph = new List<MovePointBehavior>();
		
		BuildGraph(maxDistance, 0, grid, ref graph, skipIgnoreList);

		if (!graph.Contains(targetNode))
			return null;

		Dictionary<MovePointBehavior, int> distance = new Dictionary<MovePointBehavior, int>();
		Dictionary<MovePointBehavior, MovePointBehavior> previous = new Dictionary<MovePointBehavior, MovePointBehavior>();

		foreach (MovePointBehavior node in graph)
		{
			distance.Add(node, int.MaxValue);
			previous.Add(node, null);

			tGraph.Add(node);
		}

		distance[this] = 0;
		previous[this] = null;

		while (tGraph.Count > 0)
		{
			// Find the item with the smallest distance.
			MovePointBehavior node = tGraph[0];
			for (int _i = 0; _i < tGraph.Count; _i++)
			{
				MovePointBehavior _node = tGraph[_i];

				if (grid.ignoreList.Contains(_node) && !skipIgnoreList)
					continue;

				if (distance[_node] < distance[node])
				{
					node = _node;
					MovePointBehavior tNode = tGraph[0];
					tGraph[0] = _node;
					tGraph[_i] = tNode;
				}
			}

			tGraph.RemoveAt(0);

			if (distance[node] == int.MaxValue)
				break;

			foreach (MovePointBehavior neighbor in node.neighborList)
			{
				if (neighbor == null || (!skipIgnoreList && grid.ignoreList.Contains(neighbor)) || !graph.Contains(neighbor))
					continue;

				int alt = distance[node] + 1;

				if(alt < distance[neighbor])
				{
					distance[neighbor] = alt;
					previous[neighbor] = node;
				}
			}
		}

		List<MovePointBehavior> path = new List<MovePointBehavior>();
		MovePointBehavior u = targetNode;

		while (previous[u] != null)
		{
			path.Add(u);
			u = previous[u];
		}

		path.Reverse();

		return path;
	}