新手在這里很抱歉,如果我沒有很好地描述這個問題。
我正在嘗試創建一個 8 向尋路腳本。我已經按照教程的大部分內容進行了操作,但希望將其更改為以更容易理解的方式作業。
GetNeighbours 方法在 4 個方向上作業,但不是對角線。我正在使用字典來索引節點(單元格)中的 x 和 y 值。我知道這效率不高,但對我來說更容易理解和更靈活。
無論如何,路徑僅在某些時候有效。似乎每當我需要移動到頂行或左行時,我都無法獲得相鄰的單元格。如果我在 tilemap 中放置孔,它也會弄亂路徑,但只有當我有時會在孔后面時,才會看到影像:不作業:

在職的:

任何幫助都會很棒!
public List<Node> GetNeighbours(Node node)
{
List<Node> neighbours = new List<Node>();
int checkX = node.gridX;
int checkY = node.gridY;
//left
if (nodes.ContainsKey(new Vector2Int(checkX-1, checkY)))
{
neighbours.Add(nodes[new Vector2Int(checkX-1, checkY)]);
}
//right
if (nodes.ContainsKey(new Vector2Int(checkX 1, checkY)))
{
neighbours.Add(nodes[new Vector2Int(checkX 1, checkY)]);
}
//up
if (nodes.ContainsKey(new Vector2Int(checkX, checkY 1)))
{
neighbours.Add(nodes[new Vector2Int(checkX, checkY 1)]);
}
//down
if (nodes.ContainsKey(new Vector2Int(checkX, checkY - 1)))
{
neighbours.Add(nodes[new Vector2Int(checkX, checkY - 1)]);
}
//top left
if (nodes.ContainsKey(new Vector2Int(checkX - 1, checkY - 1)) && nodes.ContainsKey(new Vector2Int(checkX, checkY 1)) && nodes.ContainsKey(new Vector2Int(checkX - 1, checkY - 1)));
{
neighbours.Add(nodes[new Vector2Int(checkX -1, checkY 1)]);
}
//top right
if(nodes.ContainsKey(new Vector2Int(checkX 1, checkY)) && nodes.ContainsKey(new Vector2Int(checkX, checkY 1)) && nodes.ContainsKey(new Vector2Int(checkX 1, checkY 1)))
{
neighbours.Add(nodes[new Vector2Int(checkX 1, checkY 1)]);
}
//bottom left
if(nodes.ContainsKey(new Vector2Int(checkX-1, checkY)) && nodes.ContainsKey(new Vector2Int(checkX, checkY -1 )) && nodes.ContainsKey(new Vector2Int(checkX - 1, checkY - 1)))
{
neighbours.Add(nodes[new Vector2Int(checkX - 1, checkY - 1)]);
}
//bottomright
if (nodes.ContainsKey(new Vector2Int(checkX 1, checkY)) && nodes.ContainsKey(new Vector2Int(checkX, checkY -1)) && nodes.ContainsKey(new Vector2Int(checkX 1, checkY - 1)))
{
neighbours.Add(nodes[new Vector2Int(checkX 1, checkY - 1)]);
}
// Debug.Log("number of neighbours added is: " neighbours.Count);
return neighbours;
}
尋路類
public class Pathfiding
{
public static List<Vector2Int> FindPath(Grid grid, Vector2Int startPos, Vector2Int endPos)
{
List<Node> nodes_path = _ImpFindPath(grid, startPos, endPos);
if (!grid.nodes.ContainsKey(startPos) || !grid.nodes.ContainsKey(endPos))
{
return null;
}
else
{
//get nodes and return a list of points
List<Vector2Int> ret = new List<Vector2Int>();
if (nodes_path != null)
{
foreach (Node n in nodes_path)
{
ret.Add(new Vector2Int(n.gridX, n.gridY)); //load all nodes to check
}
}
return ret;
}
}//end FindPath////
private static List<Node> _ImpFindPath(Grid grid, Vector2Int startPos, Vector2Int endPos)
{
Node startNode;
Node targetNode;
startNode = grid.nodes[startPos];
targetNode = grid.nodes[endPos];
List<Node> openSet = new List<Node>();
HashSet<Node> closedSet = new HashSet<Node>();
openSet.Add(startNode);
while (openSet.Count > 0)
{
Node currentNode = openSet[0];
for (int i = 1; i < openSet.Count; i )
{
//only check nodes with better f costs
if (openSet[i].fCost < currentNode.fCost || openSet[i].fCost == currentNode.fCost && openSet[i].hCost < currentNode.hCost)
{
currentNode = openSet[i];
}
}
openSet.Remove(currentNode);
closedSet.Add(currentNode);
if (currentNode == targetNode)
{
return RetracePath(grid, startNode, targetNode);
}
foreach (Node neighbour in grid.GetNeighbours(currentNode))
{
if (neighbour.walkPenalty <= 0 || closedSet.Contains(neighbour))
{
continue;
}
int newMovementCostToNeighbour = currentNode.gCost GetDistance(currentNode, neighbour) * (int)(10.0f * neighbour.walkPenalty);
if (newMovementCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour))
{
neighbour.gCost = newMovementCostToNeighbour;
neighbour.hCost = GetDistance(neighbour, targetNode);
neighbour.parent = currentNode;
if (!openSet.Contains(neighbour))
openSet.Add(neighbour);
}
}
}
return null;
}
uj5u.com熱心網友回復:
條件存在三個錯誤//top left:
陳述句末尾不應有分號
if。它使if陳述句無用,更糟糕的是它總是執行下面的塊。因此,始終存在朝向左上角的對角路徑選項。修復第一個錯誤后,您需要在條件的第一個謂詞中更改
checkY - 1為。checkYif你需要在最后一個謂詞中更改
checkY - 1為。checkY 1
//top left
if (nodes.ContainsKey(new Vector2Int(checkX - 1, checkY)) &&
nodes.ContainsKey(new Vector2Int(checkX, checkY 1)) &&
nodes.ContainsKey(new Vector2Int(checkX - 1, checkY 1)))
{
neighbours.Add(nodes[new Vector2Int(checkX -1, checkY 1)]);
}
TryGetValue使用它來避免更多的struct構造和查找會更好:
//top left
if (nodes.ContainsKey(new Vector2Int(checkX - 1, checkY)) &&
nodes.ContainsKey(new Vector2Int(checkX, checkY 1)) &&
nodes.TryGetValue(new Vector2Int(checkX - 1, checkY 1), out var n))
{
neighbours.Add(n);
}
我不確定這些是否都是您代碼中的直接錯誤,請嘗試一下。
還有一個與對角線運動有關的間接誤差。我不明白為什么您需要檢查 4-neighborhood 路徑以及對角線檢查。如果無論如何必須存在 4 個鄰居,為什么要顯式添加對角線運動?還是另一個錯誤,對于對角線移動,實際上應該省略非對角線謂詞?
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/416076.html
標籤:
