如何放置一个临时对象并通过我的A *寻路算法检测到它

时间:2017-12-02 16:42:36

标签: c# unity3d

我有一个正常运行的A *路径查找算法,我没有尝试放置一个对象,它被路径查找算法拾取,然后在它阻塞路径时被删除。我到目前为止的代码如下:

if (Physics.Raycast(ray, out hit))
{
    Vector3 testPos = new Vector3(hit.transform.position.x, hit.transform.position.y, hit.transform.position.z - 0.633f);
    if (pathFinding.TestLocation(startPos, endPos, wall, testPos))
    {
        Instantiate(wall, testPos, wall.transform.rotation);
     }

  //In the path finding algorithm class
  public bool TestLocation(Vector3 startPos, Vector3 endPos, GameObject wall, Vector3 position)
  {
    GameObject clone = Instantiate(wall, position, wall.transform.rotation);

    if (FindPath(startPos, endPos))
    {
        Debug.Log(FindPath(startPos, endPos));
        Destroy(clone);
        return true;
    } else
    {
        Destroy(clone);
        return false;
    }
}

我的代码在绑定路径时阻止对象被构建,但是一旦路径被阻止就阻止了对象的构建,这不是我想要的。我很难知道造成这种情况的原因和任何帮助都会受到赞赏。感谢。

public bool FindPath (Vector3 startPointValue, Vector3 endPointValue) {
    Vector3 startPosition = new Vector3(startPointValue.x+2.5f, startPointValue.y+0.5f, 0);
    Vector3 endPosition = new Vector3(endPointValue.x+4, endPointValue.y+1, 0);

    Node startNode = grid.NodePosition(startPosition);
    Node endNode = grid.NodePosition(endPosition);

    List<Node> possiblePaths = new List<Node>();
    HashSet<Node> triedPaths = new HashSet<Node>();
    possiblePaths.Add(startNode);

    while(possiblePaths.Count > 0)
    {
        Node currentNode = possiblePaths[0];
        for (int i = 1; i < possiblePaths.Count; i++)
        {
            if (possiblePaths[i].FCost < currentNode.FCost || possiblePaths[i].FCost == currentNode.FCost && possiblePaths[i].hCost < currentNode.hCost)
            {
                currentNode = possiblePaths[i];
            }
        }

        possiblePaths.Remove(currentNode);
        triedPaths.Add(currentNode);


        if (currentNode == endNode)
        {
            RetracePath(startNode, endNode);
            //return true;
        } /*else if (possiblePaths.Count == 0 && !triedPaths.Contains(endNode))
        {
            Debug.Log("Impossible");
            RetracePath(startNode, currentNode);
        }*/

        foreach (Node neighbour in grid.GetNeighbours(currentNode))
        {
            if (!neighbour.blocked || triedPaths.Contains(neighbour))
            {
                continue;
            }

            int newMovementCostToNeighbour = currentNode.gCost + GetDistance(currentNode, neighbour);
            if (newMovementCostToNeighbour<neighbour.gCost || !possiblePaths.Contains(neighbour))
            {
                //Debug.Log(newMovementCostToNeighbour);
                neighbour.gCost = newMovementCostToNeighbour;
                neighbour.hCost = GetDistance(neighbour, endNode);

                neighbour.parent = currentNode;

                if (!possiblePaths.Contains(neighbour))
                {
                    possiblePaths.Add(neighbour);
                }
            }
        }
        if (possiblePaths.Count == 0 && !triedPaths.Contains(endNode))
        {
            //RetracePath(startNode, possiblePaths);
            Debug.Log("is false");
            return false;
        }
    }
    return true;
}

2 个答案:

答案 0 :(得分:1)

  

yield return new WaitUntil(IsBlocked);

天哪没有。协同程序是适当的工具,特别是你如何实现它。这将是会发生的事情:

  1. 评估IsBlocked()
  2. 的返回值
  3. 假设路径被阻止,FindPath()将因阻塞而返回false
  4. IsBlocked()将返回false(旁注:这是向后!)并设置一些变量
  5. yield将停止进一步处理GetIsBlocked()(此方法中没有其他行,所以这是毫无意义的。)
  6. if (!isBlocked && check)将评估为false
  7. TestLocation()将返回false(并销毁对象)
  8. 其他Update()代码将运行,最终(在下一帧)将重新评估yield指令。
  9. IsBlocked()将再次进行评估,这次IsBlocked()将返回true(因为我们销毁了#6中的阻止对象)
  10. GetIsBlocked()将完成(但此处没有代码可以执行)。
  11. 由于未包含的更新代码,我无法猜测会发生什么奇怪的副作用。

    你应该做什么:

    1. 删除所有协程使用。
    2. 更正IsBlocked()的返回,以便是一个块 return true(这将基本上转变为可以内联的return !FindPath(a, b);
    3. if (!isBlocked && check)更改为if(IsBlocked())
    4. 您不需要变量isBlockedcheck
    5. 除此之外,你的逻辑基本上是正确的:

      • 创建阻止
      • 检查路径是否存在
      • 如果没有,请移除阻止/阻止放置/无论

答案 1 :(得分:0)

通过更新我的网格来修复它,一如既往的简单修复。 :P