#Help with PathFinding

1 messages · Page 1 of 1 (latest)

jagged marten
#

Hey guys, for some time I've been struggling with making a pathfinding system for my game.
So far I've made a Node, Graph and GraphSearch scripts according to a tutorial I found, which works perfectly for an int[,] array representing the current portion of the map (0 for passable, 1 for impassable/wall).
The thing I'm struggling with is creating this array because I don't know what kind of solution would be most efficient..

On the image below the blue spot is the enemy which will want to find it's way towards the player. When the player steps into the circle (range of enemy sight) the enemy will lock onto the player and frequently (unless the player doesn't move, then it just uses the previously generated path) try to find the best path towards him (if any exists). If the player manages to go out of the enemy range of sight (area between the red circle and red box) it will still try to follow the player but this time the pathfinding will start to loop at a much lower rate and eventually stop, providing that the player stays in this area for long enough. If the player steps out of the red box area - the chase stops immediately.

Im my code I have a float sightRange which is basically the range within the enemy can see the player (red circle on the image), float chaseBoxSize = sightRange * 1.5f (width and height of the red box, green and dark green lines on the image), float2 startingPos which is set to new float2(transform.position.x, transform.position.y) when creating a new graph, as well as a float2 endingPos which is set to new float2(_target.position.x, _target.position.y) where _target is a reference to the object Transform which is the enemy target.
I also have an int nodeMapSize which is how many nodes should there be on the graph on each axis (the more nodes, the closer they are to each other and the more accurate the search is - mostly for handling enemies of bigger sizes, so they won't bump into walls too much).
I use it to create the int[,] array mentioned earlier, which I named nodeMap and I set it to new int[nodeMapSize, nodeMapSize];

Now here comes the ugly part which I am most worried about:
First I set a variable float2 mapStart to new float2(startingPos.x - chaseBoxSize / 2, startingPos.y + chaseBoxSize / 2) which represents the world coordinates of the first node in the nodeMap (top left corner, light green dot on image).
Then I set another variable float nodeSpacing to chaseBoxSize / nodeMapSize.
Now I run a double for loop which will go through all the nodes in nodeMap and assign 0 or 1 to each of them:

for (int row = 0; row < nodeMapSize; ++row)
{
  for (int column = 0; column < nodeMapSize; ++row)
  {
    // Collide check for current node at position: 
    // new Vector3(mapStart.x + column * nodeSpacing, mapStart.y + row * nodeSpacing, 0)
    nodeMap[row, column] = collided ? 1 : 0;
  }
}

I'm not really sure how to go with the collide check here
There are two things that come to my mind.
First one is creating an empty GameObject and copy the BoxCollider2D onto this object, and then for each node change it's position to that node and check if the collider collides with any Impassable objects.
The second one is making a BoxCast for each node with the origin position set to the current node position which will check if it collides with any Impassable objects.
After this point it's all pretty simple, I just pass the nodeMap to my GraphSearch instance and let the object go from one node to another (if there is any path)

It's my first doing a pathfinding script (other than a Windows CMD console one) and from watching different types of videos I am aware that bad pathfinding (especially for multiple enities at once which is usually the case) can lead to some issues with performance

I'll gladly accept any advice related to this..

TLDR: A way to quickly check for collisions in many locations

jagged marten
#

Let this F be a proof of my code working

#

Which doesn't really mean that it's good

#

I felt a little tiny lag spike

#

either way here's the code

#

where most of the stuff takes place

#
private Graph CreateMapGraph()
{
    startingPos = new Vector2(transform.position.x, transform.position.y);
    endingPos = new Vector2(_target.position.x, _target.position.y);
    nodeMap = new int[nodeMapSize, nodeMapSize];
    mapStart = new float2(startingPos.x - chaseBoxSize / 2, startingPos.y + chaseBoxSize / 2);
    nodeSpacing = chaseBoxSize / nodeMapSize;
    for (int row = 0; row < nodeMapSize; ++row)
    {
        for (int column = 0; column < nodeMapSize; ++column)
        {
            checkPos = new Vector2(mapStart.x + column * nodeSpacing, mapStart.y - row * nodeSpacing);
            if (startNodeIndex.x == -1 && Vector2.Distance(startingPos, checkPos) <= nodeSpacing)
                startNodeIndex = new int2(row, column);
            if (endNodeIndex.x == -1 && Vector2.Distance(endingPos, checkPos) <= nodeSpacing)
                endNodeIndex = new int2(row, column);
            checkPos += colliderOffset;
            colliderHit = Physics2D.OverlapBox(checkPos, colliderSize, 0, LayerMask.GetMask("IMPASSABLE")) != null;
            nodeMap[row, column] = colliderHit ? 1 : 0;
        }
    }
    return new Graph(nodeMap);
}
#

Don't bother asking about the Graph, I'll be working on that a little later as it works for now

#

I'm just curious how can I optimize this code for now

#

as for the variables used here, most are self explanatory but you may ask if something is not