ProceduralGridMover.UpdatePath() seems to be ignoring certain objects

UPDATE:

I may have figured something out. I was playing around with AstarParth.Scan() and found that if I Scan() at the start of my game, ProceduralGridMover.UpdatePath() seems to behave as expected (even for scenes outside the current bounds of the grid oddly enough).

I suspect that this might have something to do with me caching the grid, which I don’t totally understand to be honest. I’m going to run a Scan at the start of my game and then hopefully I’m good to go?

UPDATE 2: Sorry for all the edits…it’s still a little finicky and I think the update above is more of a band-aid solution. I suppose I can run AstarPath.Scan() when I need to, it’s just that it seems to lag a bit more than ProceduralGridMover.UpdatePath()

/original post below/

Hey Aron, I’ll try and keep this simple…

My game world is divided up into scenes that are loaded additively as the player moves around. Basically each scene has a “scene node” object, and when the player moves close enough to that node it will trigger the loading of all surrounding scenes and the unloading of any scene a certain distance away.

I have a method that:

  1. Loads a scene

  2. Waits for that scene to be loaded

  3. Loads the next scene, ect.

  4. Then it loads all of the “harvestables” (think trees, rocks, etc) for that scene

  5. Then I call ProceduralGridMover.UpdatePath() to update the grid

This is all in a coroutine that waits for each scene to be loaded before progressing.

The grid successfully updates allowing the ground to be walkable but seems to ignore the rocks and trees and such. If I load the game from the title screen these same rocks and trees will be accounted for in the grid, but if I walk away from them and come back they are no longer counted…the rocks and trees are actually the same instances, I just activate/deactivate them whenever their scene is loaded…

I’m wondering if you might have any ideas on what might be causing this? Maybe my couroutine isn’t playing nice with the ProceduralGridMover?

I should also note that I set the update distance to 10000 because I wanted to update the grid manually. Previously I was having an issue where the scene terrain itself would not be counted because it was loaded after the last update (based on player distance from the grid center).

Thank you. Below is the code. It may be ugly by your standards I apologize.

IEnumerator WaitForSceneLoad(List<string> scenesToLoad)
{
    //HarvestableSpawnPoints live in each scene and will add themselves to this list so they can be activated after all scenes are loaded but before the grid update
    harvestables = new List<HarvestableSpawnPoint>(); 

    for (int i = 0; i < scenesToLoad.Count; i++)
    {
        AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(scenesToLoad[i], LoadSceneMode.Additive);

        // Wait until the asynchronous scene fully loads
        while (!asyncLoad.isDone)
        {
            yield return null;
        }          
    }

    for (int i = 0; i < harvestables.Count; i++)
    {
        harvestables[i].LoadHarvestables();
    }

    //yield return new WaitForSeconds(30f); //try and wait for everything above to finish..?

    Pathfinding.ProceduralGridMover grid = ApplicationManager.GetInstance().GetGridMover();
    grid.UpdateGraph(); //wait until this is done too
    
    while (grid.updatingGraph)
    {
        yield return null;
    }

    levelsAreLoaded = true;
    Debug.Log("levels are loaded");
}

Hi

So the ProceduralGridMover will only recalculate the nodes which really need to be recalculated. Therefore you must have a scanned/cached graph to start with, otherwise the starting area will be empty. It should update correctly as it moves around though.

Usually the reason that the ProceduralGridMover does not work in some of these cases is that it recalculates nodes in a region that you have not yet loaded. The world inside the bounds of the graph needs to be completely loaded at all times, otherwise it will not work well.

Hey Aaron, thanks for the response.

It turns out the issue was actually a timing issue between my player’s location and the new scene that needed to be scanned. Long story short, instead of moving the grid to the player’s location I now move it to central “scene node” after everything has been loaded and it looks like I’m good to go!

I do have another question though, I’ve seen you mention on this forum that the ProceduralGrid mover is meant to be used for the player only and could cause issues if there are NPCs using the grid as well. What might happen if an NPC is walking to a point when the grid is shifted? In my game if an NPC is too far away they will be deactivated, but NPCs close enough to the new central scene will have the grid moved beneath them, likely while they are using it (via AIPath.destination)

I’ve also seen you mention that Recast graphs are best for open world games. Why is that exactly? Are they more easily updated at runtime? Or maybe they allow chunking? Or maybe they can cover a huge space and you don’t have to worry about breaking it up so much?

Thanks again

1 Like

Nice that you managed to solve it!

The issue that can happen is that an NPC wants to move to a point outside the graph. It will not be able to do that but it will be able to move to the closest point on the border of the grid. If you keep your NPCs within the bounds of the grid graph everything will work nicely though.

Mostly because recast graphs can represent huge worlds without using a huge amount of memory (comparatively). A grid graph that moves is also a good solution however if you only need pathfinding in a single small part of the world at a time.

Ok thanks,sounds like it shouldn’t be a problem. if an NPC wants to move that far then they were going to be deactivated anyway. I bet I can figure out a way to detect when an NPC is stuck on the edge trying to move off the grid and deactivate them because of that as well.

But an NPC moving within the bounds of the grid before and after the grid is moved will be unaffected?

So if an NPC was making their way to node (5,6), and then the grid moves and now node (5,6) is 10 world units “north”, are they going to try and pathfind to the new postion of that node? Or does it all come down to the vector or transform that is set? I think I know the answer but I just want to be sure before I plow ahead!

Yes, it will keep on working.

The included movement scripts for grid graphs all copy the relevant positions of the nodes when the path is calculated. They don’t care what happens to the nodes afterwards. They could even be destroyed, it wouldn’t matter.

Awesome, much appreciated

1 Like