I'm procedurally generating a map of hex cells and creating a variety of paths along this grid. As I'm creating these paths every about 10 runs of the game, Unity is running out of memory while generating said paths. I'm new to advanced programming like this and I'm not sure how to track down where my problems are and how I can go about fixing them. Here is an image of the Unity error message:
The general approach for the path generation is this:
- First create and instantiate a grid of hex cells for a certain region size.
- Create a set of randomly distributed points within the region size using Poisson disc sampling
- Then take these points and assign them to there corresponding cells, and convert the cells to a hex node, creating a list of "encounters"
- I then have 2 functions for finding a horizontal path or vertical path between these encounter nodes. These functions basically just search around the starting node for the closest encounter points and adds them to list a connections, and then choices a random connected point and moves to it as long as it is valid, then repeat.
Here's the code:
static List<HexNode> GetConnections(HexNode currentNode)
{
List<HexCell> connections = new List<HexCell>();
List<HexCell> conectList = new List<HexCell>();
List<HexCell> searchList = new List<HexCell>();
HexCell currentCell = currentNode.cell;
int loops = Mathf.CeilToInt(radius + 1);
searchList.Add(currentCell);
for (int i = 0; i < loops; i++)
{
conectList.Clear();
foreach (HexCell c in searchList)
{
foreach (HexCell n in c.neighbors)
{
if (n != null && n != currentCell)
{
if (!connections.Contains(n))
{
connections.Add(n);
}
conectList.Add(n);
}
}
}
searchList.Clear();
foreach (HexCell c in conectList)
{
searchList.Add(c);
}
}
List<HexNode> connectedNodes = new List<HexNode>();
foreach(HexNode encounter in nodes)
{
if (connections.Contains(encounter.cell))
{
connectedNodes.Add(encounter);
}
}
return connectedNodes;
}
public static List<HexCell> VerticalPath(int number)
{
List<HexNode> topNodes = new List<HexNode>();
foreach(HexNode node in nodes)
{
if(node.cell.offsetCoordinates.y > regionSize.y * .9f)
{
if(number == 1) // Left path
{
if (node.cell.offsetCoordinates.x < regionSize.x * .33f)
{
topNodes.Add(node);
}
}
else if(number == 2) // Middle path
{
if (node.cell.offsetCoordinates.x > regionSize.x * .33f && node.cell.offsetCoordinates.x < regionSize.x * .66f)
{
topNodes.Add(node);
}
}
else if(number == 3) // Right path
{
if (node.cell.offsetCoordinates.x > regionSize.x * .66f)
{
topNodes.Add(node);
}
}
}
}
HexNode startNode = topNodes[Random.Range(0, topNodes.Count)];
HexNode endNode = new HexNode();
bool searching = true;
HexNode currentNode = startNode;
while (searching)
{
List<HexNode> connections = GetConnections(currentNode);
List<HexNode> validMoves = new List<HexNode>();
foreach (HexNode node in connections)
{
if (node.cell.coordinates.Z < currentNode.cell.coordinates.Z)
{
validMoves.Add(node);
}
}
if (validMoves.Count < 1)
{
endNode = currentNode;
searching = false;
}
else
{
int rand = Random.Range(0, validMoves.Count);
validMoves[rand].previousNode = currentNode;
currentNode = validMoves[rand];
}
}
return RetracePath(startNode, endNode);
}
After getting the list of encounters along the path I then use A* pathfinding to make a full path along all of the cells:
public static List<HexCell> FindPath(HexCell startCell, HexCell endCell)
{
HexNode startNode = ConvertNode(startCell);
HexNode endNode = ConvertNode(endCell);
List<HexNode> openList = new List<HexNode>();
List<HexNode> closedList = new List<HexNode>();
openList.Add(startNode);
startNode.gCost = 0;
startNode.hCost = DistanceTo(startNode, endNode);
while (openList.Count > 0)
{
HexNode currentNode = openList[0];
for (int i = 1; i < openList.Count; i++)
{
if (openList[i].fCost < currentNode.fCost || openList[i].fCost == currentNode.fCost && openList[i].hCost < currentNode.hCost)
{
currentNode = openList[i];
}
}
openList.Remove(currentNode);
closedList.Add(currentNode);
if (currentNode.position == endNode.position)
{
endNode = currentNode;
return RetracePath(startNode, endNode);
}
foreach (HexNode neighbor in GetNeighbors(currentNode))
{
if (closedList.Contains(neighbor))
{
continue;
}
int newMoveCost = currentNode.gCost + DistanceTo(currentNode, neighbor);
if (newMoveCost < neighbor.gCost || !openList.Contains(neighbor))
{
neighbor.gCost = newMoveCost;
neighbor.hCost = DistanceTo(currentNode, endNode);
neighbor.previousNode = currentNode;
if (!openList.Contains(neighbor))
{
openList.Add(neighbor);
}
}
}
}
return null;
}
I'm not sure exactly where my issue is but I feel like I'm creating way to many lists and references.
static List<HexCell> RetracePath(HexNode startNode, HexNode endNode)
{
List<HexCell> path = new List<HexCell>();
HexNode currentNode = endNode;
while (currentNode != startNode)
{
path.Add(currentNode.cell); // 368
currentNode = currentNode.previousNode;
}
path.Add(currentNode.cell);
path.Reverse();
return path;
}

HexPathfindingline 368. Which line is 368? If a pathfinding algorithm is encountering an out-of-memory error, there may be a logic error causing an infinite loop (e.g. the path-finding algorithm is moving in a circle and not discounting hexes it's already searched). \$\endgroup\$currentNodeandstartNode(close towhile (currentNode != startNode)) are not copies (i.e. you created them separately but they have the same values), it is possible that your program can't interpret them as equal unless you overload some functions that specifically do that. \$\endgroup\$HorizontalPath, which is in the error call stack. \$\endgroup\$