Создание соседей следопыта

Я пытаюсь создать соседей моего искателя пути, но при этом исходный путь (путь) синего цвета также закрывается. Я пробовал переключать порядок спавна, но это, похоже, не решает проблему. Совершенно новичок в Unity и был бы признателен за любое понимание того, как я могу создать путь к соседям, не теряя исходный синий путь.

Получение соседей пути; путь нереста + соседи

for (int i = 1; i < path.Count; i++)
{
    var pathCellPosition = path[i];
    pathCellPosition.Position = new Vector3(pathCellPosition.Position.x, pathPrefab.transform.position.y, pathCellPosition.Position.z);
   
    List<Node> neighbours = GetNeighbours(pathCellPosition);
    var p = Instantiate(pathPrefab, pathCellPosition.Position, Quaternion.identity, PathCells);

    foreach (Node n in neighbours)
    {
        neighbourPrefab.GetComponentInChildren<Text>().text = n.Cost.ToString();
        Instantiate(neighbourPrefab, n.Position, Quaternion.identity, p.transform);            
    }

}

Исходный путь Создание соседей следопыта

Путь перекрыт соседями Создание соседей следопыта

Реализованы предложения, устраняющие часть проблемы

Плитки вокруг теперь появляются, но при применении того же решения для реализации соседей соседей кажется, что это вызывает перекрытие с исходными соседними узлами. Создание соседей следопыта

Изменения кода:

    HashSet<Node> visitedNodes = new HashSet<Node>();
    for (int i = 1; i < path.Count; i++)
    {
        var pathCellPosition = path[i];
        visitedNodes.Add(path[i]);
        pathCellPosition.Position = new Vector3(pathCellPosition.Position.x, pathPrefab.transform.position.y, pathCellPosition.Position.z);
       
        List<Node> neighbours = GetNeighbours(path[i]);

        int fCost = DistanceFromStart(pathCellPosition) + HCostDistanceFromEndNode(pathCellPosition) + pathCellPosition.Cost;
        pathPrefab.GetComponentInChildren<Text>().text = fCost.ToString();
        var p = Instantiate(pathPrefab, pathCellPosition.Position, Quaternion.identity, PathCells);

        for(int x = 0; x < neighbours.Count; x++)
        {
            var node = neighbours[x];
            if (visitedNodes.Contains(node))
            {
                continue;
            }
            visitedNodes.Add(node);
            fCost = DistanceFromStart(node) + HCostDistanceFromEndNode(node) + node.Cost;
            neighbourPrefab.GetComponentInChildren<Text>().text = fCost.ToString();
            Instantiate(neighbourPrefab, node.Position, Quaternion.identity, p.transform);

            List<Node> NeighBourOfNeighbourNodes = GetNeighbours(node);

            if (NeighBourOfNeighbourNodes.Count > 0)
            {
                for (int y = 0; y < NeighBourOfNeighbourNodes.Count; y++)
                {
                    var neighbourNode = NeighBourOfNeighbourNodes[y];
                    if (visitedNodes.Contains(neighbourNode))
                    {
                        continue;
                    }
                    visitedNodes.Add(neighbourNode);
                    fCost = DistanceFromStart(neighbourNode) + HCostDistanceFromEndNode(neighbourNode) + neighbourNode.Cost;
                    nofn.GetComponentInChildren<Text>().text = fCost.ToString();
                    Instantiate(nofn, neighbourNode.Position, Quaternion.identity, p.transform);
                }
            }
        }

Если я не рисую соседа соседей, это выглядит правильно. Но если я делаю соседние соседи, фиолетовые не появляются так часто, как должны. До: Создание соседей следопыта

После: Создание соседей следопыта

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
30
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Типичное простое решение — перед добавлением проверить, является ли узел частью пути. Для этого может подойти HashSet, но вам понадобится что-то, что можно надежно сравнить.

Возможно что-то вроде этого:

var visitedNodes = new HashSet<Node>(path);
for (int i = 1; i < path.Count; i++)
{
    var pathCellPosition = path[i];
    pathCellPosition.Position = new Vector3(pathCellPosition.Position.x, pathPrefab.transform.position.y, pathCellPosition.Position.z);
   
    List<Node> neighbours = GetNeighbours(pathCellPosition);
    var p = Instantiate(pathPrefab, pathCellPosition.Position, Quaternion.identity, PathCells);

    foreach (Node n in neighbours)
    {
        if (visitedNodes.Contains(n))
             continue;
         visitedNodes.Add(n);
        neighbourPrefab.GetComponentInChildren<Text>().text = n.Cost.ToString();
        Instantiate(neighbourPrefab, n.Position, Quaternion.identity, p.transform);            
    }

}

Вы также можете использовать тот же подход, чтобы убедиться, что сосед не добавляется дважды.

Если вам нужно несколько уровней от узла, вам может потребоваться выполнить что-то вроде поиска с первым вдохом, в идеале отслеживая расстояние от исходного пути. Следующий общий код должен обходить граф в ширину, просто используйте path в качестве первого параметра и метод GetNeighbours в качестве второго.

public static IEnumerable<(T Node, int Distance)> GetNeighborsWithDistance<T>(IEnumerable<T> self, Func<T, IEnumerable<T>> selector)
{
    var stack = new Queue<(T Node, int Distance)>();
    var visited = new HashSet<T>();
    foreach (var node in self)
    {
        stack.Enqueue((node, 0));
    }
    while (stack.Count > 0)
    {
        var current = stack.Dequeue();
        if (visited.Contains(current.Node))
            continue;

        yield return current;
        visited.Add(current.Node);
        foreach (var child in selector(current.Node))
        {
            stack.Enqueue((child, current.Distance+ 1));
        }
    }
}

Это должно гарантированно возвращать узлы в порядке удаления от исходного пути, поэтому просто выполните .TakeWhile(p => p.Distance < DesiredDistanceFromOriginalPath), чтобы получить столько узлов, сколько хотите.

Спасибо за предложение! Это исправило для меня проблему с соседним узлом, но когда я пытаюсь создать соседей соседей, эти новые соседи в конечном итоге перекрываются с предыдущими соседями. Я не уверен, почему. Я чувствую, что ваше решение должно было решить эту проблему.

Krellex 18.03.2022 12:44

@Krelex Смотрите редактирование, вам, вероятно, просто нужно добавить соседние узлы в hashSet.

JonasH 18.03.2022 12:47

Спасибо, что вернулись снова. Я обновил, как вы предложили, но, похоже, приоритет отдается соседям соседей как первоначальным соседям. Я обновил сообщение, чтобы показать изображения и код

Krellex 18.03.2022 13:00

@Krellex, ваше редактирование, вероятно, должно быть новым вопросом, но я добавил раздел о получении узлов на произвольном расстоянии от исходного пути.

JonasH 18.03.2022 13:23

Другие вопросы по теме