Пожалуйста, опишите ошибку

Нашли баг? Помогите нам его исправить, заполнив эту форму

Новое в блоге: Анимация Skeleton

Поиск пути в Unity 3D

Максим Некрасов
Разработчик игр

Каждый день программисты сталкиваются с разными интересными ситуациями и оставляют их решение при себе. Недавно я столкнулся с одной проблемой и захотел поделиться своим опытом с широкой общественностью.

unity 2

Проблема была тривиальной, на первый взгляд, и заключалась в необходимости реализовать поиск пути в игровом движке Unity 3D.

Недолго думая, я решил обратиться к Google за ответом на вопрос. Перейдя по первым ссылкам, я вспомнил о великолепном инструменте NavMesh (Navigation Mesh), который отвечал за автоматический поиск пути. Я воспользовался этой технологией, и на это у меня ушло совсем немного времени, а программный код был мал и понятен.

void Start () {

        navAgent = GetComponent();
        if (navAgent == null) {
            Debug.Log("Не найден компонент NavMeshAgent на игроке.");
        }

        animator = GetComponent();
        if (animator == null) {
            Debug.Log("Не найден компонент Animator на игроке.");
        }

        // Создаём объекты на карте
        for(int i = 0; i < 500; i++) {
            SpawnObject(GetRandomPos());
        }
    }
    
    void Update () {

        if (Move) {
            // Проверка расстояния до точки
            if (navAgent.remainingDistance <= 1) {
                animator.SetFloat("Forward", 0);
                Move = false;
            }               
        }
        else {
            // Поиск новой точки
            path = new NavMeshPath();
            endPath = GetRandomPos();

            navAgent.CalculatePath(endPath, path);
            if (path.status == NavMeshPathStatus.PathComplete) {
                navAgent.SetDestination(endPath);
                animator.SetFloat("Forward", 0.4f);
                Move = true;
            }                
        }
    }

Изначально я знал, что данная технология не особо применима к динамическим уровням. Всё из-за того, что меш навигации рассчитывается за счёт статичных объектов на карте. Но желание потратить меньше времени плюс простота решения проблемы взяли верх, и я решил попробовать.

Всё было хорошо, персонаж отлично двигался от точки к точке, но чем больше я создавал объектов, тем чаще происходили глюки в программе. Пытаясь это исправить, я потратил достаточное количество времени, но так ни к чему и не пришёл.

Плюсы данного решения были в том, что все расчёты делал игровой движок с наименьшими затратами ресурсов производительности. Мне нужно было только давать ему точки и заставлять персонажа двигаться к ним. Объекты создаются динамически и могут располагаться как угодно.

Не дав разочарованию и усталости взять верх, я решил найти другое решение данной ситуации. Начав искать алгоритмы поиска пути, я нашёл «Алгоритм поиска А*», он был прост и очень понятен.

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

public void StartGame() {...}

private void SpawnPlayer() {...}

private void SpawnObject(int x, int z) {...}

public MatrixCell GetRandomCell() {...}

public void MathPath() {...}

private void GetEndPoint() {...}

private List GeneratePoints() {...}

IEnumerator CalculatePath() {...}

private void AddOpenCell(MatrixCell cell) {...}

private bool ContainsClose(MatrixCell conCell) {...}

private bool ContainsOpen(MatrixCell conCell) {...}

private static int GetHeuristicPathLength(MatrixCell from, MatrixCell to) {...}

Код стал намного больше начального, появились новые классы, отвечающие за расчёт движения.

Начав реализовывать этот алгоритм, я был сильно удивлён, когда понял, что на его реализацию ушло намного меньше времени, чем на решение проблем с NavMesh.

Все недостатки компенсировались хорошим результатом. Персонаж отлично ходил от одной точки к другой при разном количестве объектов.

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

Читать и комментировать
Web-components

Кирилл Торгашин

11 ноября 2016

Web-components

Управление состояниями с помощью Grox и RxJava
Unreal Engine 4. Не Unity единым!

Александр Мяоц

14 июня 2016

Unreal Engine 4. Не Unity единым!

Работа с JSON в MySQL

Максим Лимонов

9 января

Работа с JSON в MySQL

Краснодар

Коммунаров, 268,
3 эт, офисы 705, 707

+7 (861) 200 27 34

Хьюстон

3523 Brinton trails Ln Katy

+1 833 933 0204

Москва

+7 (495) 145-01-05