public List<GraphEdge> AStar(Vector3 start, Vector3 end)
    {
        List<float> gCosts = new List<float>();
        List<float> fCosts = new List<float>();

        List<GraphEdge> spt = new List<GraphEdge>(); // shortest path tree
        List<GraphEdge> searchFrontier = new List<GraphEdge>();

        for (int i = 0; i < Nodes.Count; ++i)
        {
            gCosts.Add(9999);
            fCosts.Add(9999);
            searchFrontier.Add(new GraphEdge(-1, -1));
        }

        BinaryHeap pq = new BinaryHeap();

        int index = 0;
        while (pq.Count() == 0 && index < Nodes.Count)
        {
            // check if we've found the node we want to start at
        #if USE_XZ
            if (Nodes[index].GetPosition().x == start.x && Nodes[index].GetPosition().z == start.z)
        #else // USE_ZY
            if (Nodes[index].GetPosition().x == start.x && Nodes[index].GetPosition().y == start.y)
        #endif //USE_XZ
            {
                pq.Add(0, index); // add it to our pq
                gCosts[index] = 0; // set its g cost
                fCosts[index] = 0; // set its f cost
                searchFrontier[index] = new GraphEdge(index, index); // add it to frontier
            }
            ++index;
        }

        Vector2 endPosV2;
        #if USE_XZ
        endPosV2 = new Vector2(end.x, end.z);
        #else //USE_XY
        endPosV2 = new Vector2(end.x, end.y);
        #endif
        while (pq.Count() > 0)
        {
            int closestNode = pq.Values(0);
            pq.RemoveAt(0);

            if (!spt.Contains(searchFrontier[closestNode]))
                spt.Add(searchFrontier[closestNode]); // if I use insert here, then later I can index it instead of searching for it

            Vector2 curPositionV2 = new Vector2(Nodes[closestNode].GetPosition().x,
        #if USE_XZ
            Nodes[closestNode].GetPosition().z);
        #else
            Nodes[closestNode].GetPosition().y);
        #endif
            if (curPositionV2 == endPosV2)
            {
                return spt;
            }

            GraphNode curNode = Nodes[closestNode];

            for (int i = 0; i < curNode.mEdges.GetSize(); ++i)
            {
                // index of the node that this edge is pointing to
                int edgeToIndex = curNode.mEdges.Loc(i).GetToIndex();

                float g = gCosts[curNode.GetIndex()] + (curNode.GetPosition() - Nodes[edgeToIndex].GetPosition()).sqrMagnitude;
                float h = (end - Nodes[edgeToIndex].GetPosition()).sqrMagnitude;
                float f = g + h;

                // this is where I would index for the edge
                //if (searchFrontier[edgeToIndex].GetToIndex() == -1 &&
                 //   searchFrontier[edgeToIndex].GetFromIndex() == -1)
                bool onFrontier = false;
                for (int j = 0; j < searchFrontier.Count; +++j)
                {
                    if (searchFrontier[j].GetToIndex() == edgeToIndex)
                    {
                        onFrontier = true;
                        break;
                    }
                }

                if (!onFrontier)
                {
                    searchFrontier[edgeToIndex] = curNode.mEdges.Loc(i);

                    gCosts[edgeToIndex] = g;
                    fCosts[edgeToIndex] = f;

                    if (pq.ContainsValue(edgeToIndex))
                    {
                        int pqIndex = pq.IndexOfValue(edgeToIndex);

                        float oldFCost = pq.Keys(pqIndex);

                        if (f < oldFCost) // if path is shorter
                        {
                            pq.RemoveAt(pqIndex);
                            pq.Add(f, edgeToIndex);
                        }
                    }
                    else
                    {
                        pq.Add(f, edgeToIndex);
                    }
                }
                else
                {
                    int indexOfEdgeToIndex = pq.IndexOfValue(edgeToIndex);

                    if (indexOfEdgeToIndex >= 0 && f < pq.Keys(indexOfEdgeToIndex))
                    {
                        pq.RemoveAt(indexOfEdgeToIndex);
                        pq.Add(f, edgeToIndex);
                    }
                }
            }

        }

        //Debug.LogWarning("Path to destination not found");
        spt = new List<GraphEdge>(); // clear the list to represent no path found
        return spt;
    }