Cloning a graph in realtime

  • A* version: 5.4.6
  • Unity version: 6000.3.10f1

Hi, just wondered if there was an efficient way to copy/clone a recast graph?

I use multiple graphs (in fixed positions), and sometimes they are of the same area, so one great optimisation to avoid a graph rescan would be if I could copy/clone a recast graph.

I’ve searched and found mention of using SerializeGraph, which I’ve tested:

    public byte[] CloneGraph()
    {
        return AstarPath.active.data.SerializeGraph(new Pathfinding.Serialization.SerializeSettings { nodes = true }, graph);
    }

    public IEnumerator RestoreGraph(byte[] serializedGraph)
    {
        if (graph != null)
        {
            AstarData activeData = AstarPath.active.data;
            activeData.RemoveGraph(graph);
        }

        NavGraph[] result = AstarPath.active.data.DeserializeGraphsAdditive(serializedGraph);
        graph = result[0] as RecastGraph;

        graph.name = $"Graph_{GetName()}";

        yield return PositionGraph(centreTile.Centre.x, centreTile.Centre.z);
    }

Unfortunately, its quite slow for realtime use and most of the time a graph.Scan() is actually faster - which is impressive, but that still takes fair bit of processing time.

Since a graph has already been scanned (which surely must be quite heavy work), and the graph is there in memory, I was wondering if there was a way to take a copy of it?

Hi

Probably the best solution at the moment is to use

AstarPath.active.data.DuplicateGraph()

to duplicate the settings of the graph, and then transfer node data using

var tileMeshes = originalGraph.ToTileMeshes()
newGraph.ReplaceTiles(tileMeshes);

I have not verified that this works, but I think it should.

Thanks @aron_granberg, this is looking good so far!

Graph operation to Scan took 140 ms
Graph operation to copy/restore took 43 ms

    public TileMeshes CopyGraph()
    {
        return graph.ToTileMeshes();
    }

    public void RestoreGraph(TileMeshes tileMeshes)
    {
        if (graph != null)
        {
            AstarData activeData = AstarPath.active.data;
            activeData.RemoveGraph(graph);
        }

        CreateGraph();

        AstarPath.active.AddWorkItem(() => {
            graph.ReplaceTiles(tileMeshes);
        });

        AstarPath.active.FlushWorkItems();
    }