Алгоритм обхода препятствий

Форум для всего, что связано с ИИ.

Алгоритм обхода препятствий

Сообщение cyberspace_ru 12 мар 2013, 21:01

Скрипт для обхода препятствий. Предназначен исключительно для мобов, которые ходят по небольшой определенной локации, и ждут пока к ним не приблизиться Player на какую-то дистанцию. Скрипт должен быть прикреплен к мобу. И использоваться из ядра ИИ моба.
Не знаю насколько это решение разумно, но суть такова - от объекта до цели создается сетка из триггеров, которые "сканируют" местность на присутствие (или отсутствие :D ) препятствия. Затем каждый триггер передает данные на карту состоящею из объектов Cell (кладем просто аккуратно в папку со всеми скриптами):
Синтаксис:
Используется csharp
public class Cell
{

    public bool passable; //Проходима ли клетка
    public int F; // Значение в клетке
    public bool begin; // начало пути
    public bool back; // конец пути
    public int G; // цена пути от начала
    private Cell parent;
    public int x, y;


    public Cell()
    {
        passable = true;
        G = 0;
    }

    public Cell GetParrent()
    {
        if (parent == null)
            return null;
        return parent;
    }

    public void SetParent(Cell cell)
    {
        parent = cell;
    }

    public void SetLocale(int x, int y) // установим местонахождение на карте
    {
        this.x = x;
        this.y = y;
    }
}


В последствий эта карта обрабатывается по упрощенному мною алгоритму А*. Так как этот скрипт решает задачу "Прогулки", то есть животное просто бегает по лесу на определенной территории - я не усложняю алгоритм поиска.

Сам скрипт (его мы и крепим на моба):
Синтаксис:
Используется csharp
using UnityEngine;
using System;
using System.Collections.Generic;

public class PathBuilding : MonoBehaviour
{

    Transform Aim; // сюда нужно прийти
    public GameObject ScannerPrefab; // Префаб клетки
    public int size; // Размер ячеек size*size
    public int FiledExtendet; // насколько ячеек расширить поле
    GameObject[,] MapForTrassing; // карта для трассировки
    int x, y;// размер карты Cell
    float delay; // задержка для того чтобы FieldPrefab's смогли определить проходима ли клетка
    GameObject parent;
    Cell[,] map;
    bool begin, back; // у нас есть начало и конец, если true
    // Переменные описывающие размеры основного поля
    // нумерация по часовой стрелки от AI
    Vector3 vertex1; // AI
    Vector3 vertex2; // правый нижний угол относитeльно AI
    Vector3 vertex3; // AIM
    Vector3 vertex4;
    bool step1 = true, step2 = true;
    bool pathComplete; // если true, то есть готовый путь
    bool error;


    void Start()
    {
        ScannerPrefab.GetComponent<BoxCollider>().size = new Vector3(size, ScannerPrefab.GetComponent<BoxCollider>().size.y, size);
        FiledExtendet *= size;
    }

    void Update()
    {
        if (delay <= 0)
        {
            if (step1 == false) // создание объектов для сбора данных
            {
                error = false;
                begin = back = false;
                x = y = 0;
                // Заполняем массив MapForTrassing
                vertexRectDeterm();
                step1 = true;
            }
            else if (step2 == false)
            {
                for (int i = 0; i < x; i++)
                    for (int k = 0; k < y; k++)
                    {
                        map[i, k].SetLocale(i, k);
                        if (MapForTrassing[i, k] == null)
                        {
                            Error();
                            return;
                        }
                        map[i, k].passable = MapForTrassing[i, k].GetComponent<Scanner>().GetPassable();
                        // Поиск начала и конца пути
                        if (begin == false && Vector3.Distance(this.gameObject.transform.position, MapForTrassing[i, k].gameObject.transform.position) <= size && map[i, k].passable == true)
                        {
                            map[i, k].begin = true;
                            begin = true;
                        }
                        else if (back == false && Vector3.Distance(Aim.transform.position, MapForTrassing[i, k].gameObject.transform.position) <= size && map[i, k].passable == true)
                        {
                            map[i, k].back = true;
                            back = true;
                        }
                    }
                Seacrh(); // сам поиск пути
                step2 = true;
            }
        }
        else delay -= Time.deltaTime;
    }


    public bool GetError() // если true, то была ошибка
    {
        return error;
    }


    public bool GetComplete() // возвращает true, если путь найден
    {
        return pathComplete;
    }

    public Transform[] GetPath()
    {

        Cell cell = backPath; // получили точку конечного пути*/
        List<Transform> mass = new List<Transform>();
        while (true)
        {
            if (MapForTrassing[cell.x, cell.y] != null && Vector3.Distance(MapForTrassing[cell.x, cell.y].transform.position, this.transform.position) > size)
            {
                // Добавляем Scanner's в путь
                MapForTrassing[cell.x, cell.y].GetComponent<Scanner>().Activated();
                mass.Add(MapForTrassing[cell.x, cell.y].transform);
            }
            if (cell.GetParrent() == null)
                break;
            cell = cell.GetParrent();
        }
        pathComplete = false;
        foreach (GameObject element in MapForTrassing)
            if (element.GetComponent<Scanner>().GetON() == false)
                GameObject.Destroy(element);
        if (mass == null)
            Error();
        if (Aim != null)
            GameObject.Destroy(Aim.gameObject);
        return mass.ToArray();
    }


    public void CtreatePath(Transform Aim)
    {
        step1 = step2 = false;
        this.Aim = Aim;
    }


    void getKorrdinate(Cell cell, out int _x, out int _y)
    {
        _x = cell.x;
        _y = cell.y;
    }

    void Error() // Вставить туда где выходят ошибки!
    {
        error = true;
        step1 = step2 = true;
        pathComplete = false;
    }

    #region Сам алгоритм построения пути
    List<Cell> queue; // очередь
    List<Cell> closeCells; // ячейки которые отработаны и больше не нужны
    Cell backPath; // конец пути

    void Seacrh()
    {
        if (back == false || begin == false)
            Error();
        else
        {
            queue = new List<Cell>();
            closeCells = new List<Cell>();
            queue.Add(GetBeginCell()); // добавляем начальную точку в очередь
            backPath = GetBackCell();
            Generation();
            pathComplete = true;
        }
    }

    void Generation() // А*, запускает алгоритм
    {
        while (true)
        {
            Cell cell;
            if (queue.Count > 0)
            {
                cell = GetValidationCell();
                closeCells.Add(cell);
                queue.Remove(cell);
            }
            else
            {
                Error();
                break;
            }
            List<Cell> wave = new List<Cell>();
            if (cell.x + 1 < x && map[cell.x + 1, cell.y].passable == true && CloseCell(map[cell.x + 1, cell.y]) == false)
            {
                map[cell.x + 1, cell.y].SetParent(cell);
                map[cell.x + 1, cell.y].F = GetExresticalH(map[cell.x + 1, cell.y]);
                wave.Add(map[cell.x + 1, cell.y]);
            }
            if (cell.x - 1 > -1 && map[cell.x - 1, cell.y].passable == true && CloseCell(map[cell.x - 1, cell.y]) == false)
            {
                map[cell.x - 1, cell.y].SetParent(cell);
                map[cell.x - 1, cell.y].F = GetExresticalH(map[cell.x - 1, cell.y]);
                wave.Add(map[cell.x - 1, cell.y]);
            }
            if (cell.y + 1 < y && map[cell.x, cell.y + 1].passable == true && CloseCell(map[cell.x, cell.y + 1]) == false)
            {
                map[cell.x, cell.y + 1].SetParent(cell);
                map[cell.x, cell.y + 1].F = GetExresticalH(map[cell.x, cell.y + 1]);
                wave.Add(map[cell.x, cell.y + 1]);
            }
            if (cell.y - 1 > -1 && map[cell.x, cell.y - 1].passable == true && CloseCell(map[cell.x, cell.y - 1]) == false)
            {
                map[cell.x, cell.y - 1].SetParent(cell);
                map[cell.x, cell.y - 1].F = GetExresticalH(map[cell.x, cell.y - 1]);
                wave.Add(map[cell.x, cell.y - 1]);
            }
            bool exitFlag = false;
            foreach (Cell elements in wave)
            {
                if (elements == backPath)
                    exitFlag = true;
                else if (OpenCell(elements) == false) // ячейка не находиться в открытом списке
                    queue.Add(elements);
            }
            if (exitFlag == true)
                break;
        }
    }

    Cell[,] getMap()
    {
        return map;
    }

    Cell GetValidationCell() // получает самую перспективную ячеку из Queue
    {
        Cell max = queue[queue.Count - 1];
        foreach (Cell element in queue)
            if (element.F < max.F)
                max = element;
        return max;
    }


    int GetExresticalH(Cell cell)
    {
        int H = 0;
        int xDistance = Math.Abs(cell.x - backPath.x);
        int yDistance = Math.Abs(cell.y - backPath.y);
        if (xDistance > yDistance)
            H = 14 * yDistance + 10 * (xDistance - yDistance);
        else
            H = 14 * xDistance + 10 * (yDistance - xDistance);
        return H;
    }

    bool OpenCell(Cell cell)
    {
        foreach (Cell element in queue)
            if (element == cell)
                return true;
        return false;

    }

    bool CloseCell(Cell cell) // есть ли эта клетка в закрытом списке
    {
        foreach (Cell element in closeCells)
            if (element == cell)
                return true;
        return false;
    }

    Cell GetBeginCell() // получить начальную точку
    {

        for (int i = 0; i < x; i++)
            for (int k = 0; k < y; k++)
                if (map[i, k].begin == true)
                    return map[i, k];
        return null;
    }


    Cell GetBackCell() // получить конечную точку
    {
        for (int i = 0; i < x; i++)
            for (int k = 0; k < y; k++)
                if (map[i, k].back == true)
                    return map[i, k];
        return null;
    }
    #endregion




    #region Приводит сетку для заполнения

    void vertexRectDeterm() // задаем вершины поля
    {
        // наши координаты
        float x1 = this.transform.position.x;
        float z1 = this.transform.position.z;
        // координаты объекта конца пути
        float x2 = Aim.transform.position.x;
        float z2 = Aim.transform.position.z;
        float height = Aim.transform.position.y;
        if (x1 < x2 && z1 < z2) // 1
        {
            vertex1 = new Vector3((int)x1 - FiledExtendet, height, (int)z1 - FiledExtendet);
            vertex2 = new Vector3((int)x2 + FiledExtendet, height, (int)z1 - FiledExtendet);
            vertex3 = new Vector3((int)x2 + FiledExtendet, height, (int)z2 + FiledExtendet);
            // дальше расширяем границы, так чтобы ячеки размером size на size корректно встали
            while (true)
                if ((int)vertex3.x % size == 0)
                    break;
                else
                    vertex3 = new Vector3((int)vertex3.x + 1, height, (int)vertex3.z);
            while (true)
                if ((int)vertex3.z % size == 0)
                    break;
                else
                    vertex3 = new Vector3((int)vertex3.x, height, (int)vertex3.z + 1);
            vertex4 = new Vector3((int)x1 - FiledExtendet, height, (int)z2 + FiledExtendet);
            parent = (GameObject)Instantiate(ScannerPrefab, this.transform.position, new Quaternion(0, 0, 0, 0));
            MapForTrassing = new GameObject[x = (((int)vertex4.z - (int)vertex1.z) / size), y = (((int)vertex2.x - (int)vertex1.x) / size)]; // массив точек путей столбцы - строки
            map = new Cell[x, y];
            for (int i = 0; i < x; i++)
                for (int k = 0; k < y; k++)
                    map[i, k] = new Cell();
            for (int i = 0; i < x; i++)
                for (int k = 0; k < y; k++)
                {
                    MapForTrassing[i, k] = (GameObject)Instantiate(ScannerPrefab, new Vector3(vertex1.x + k * size + 0.5f, height, vertex1.z + i * size + 0.5f), new Quaternion(0, 0, 0, 0)); // создаем ячейку
                    MapForTrassing[i, k].transform.parent = parent.transform; // отдaем ее родителю, общему для группы ячеек
                    MapForTrassing[i, k].GetComponent<Scanner>().SetAI(this.gameObject);
                }
        }
        else if (x1 > x2 && z1 > z2)// 2
        {
            vertex1 = new Vector3((int)x1 + FiledExtendet, height, (int)z1 + FiledExtendet);
            vertex2 = new Vector3((int)x2 - FiledExtendet, height, (int)z1 + FiledExtendet);
            vertex3 = new Vector3((int)x2 - FiledExtendet, height, (int)z2 - FiledExtendet);
            // дальше расширяем границы, так чтобы ячеки размером size на size корректно встали
            while (true)
                if ((int)vertex3.x % size == 0)
                    break;
                else
                    vertex3 = new Vector3((int)vertex3.x - 1, height, (int)vertex3.z);
            while (true)
                if ((int)vertex3.z % size == 0)
                    break;
                else
                    vertex3 = new Vector3((int)vertex3.x, height, (int)vertex3.z - 1);
            vertex4 = new Vector3((int)x1 + FiledExtendet, height, (int)z2 - FiledExtendet);
            parent = (GameObject)Instantiate(ScannerPrefab, this.transform.position, new Quaternion(0, 0, 0, 0));
            MapForTrassing = new GameObject[x = (((int)vertex2.z - (int)vertex3.z) / size), y = ((int)vertex4.x - (int)vertex3.x) / size]; // массив точек путей столбцы - строки
            map = new Cell[x, y];
            for (int i = 0; i < x; i++)
                for (int k = 0; k < y; k++)
                    map[i, k] = new Cell();
            for (int i = 0; i < x; i++)
                for (int k = 0; k < y; k++)
                {
                    MapForTrassing[i, k] = (GameObject)Instantiate(ScannerPrefab, new Vector3(vertex3.x + k * size + 0.5f, height, vertex3.z + i * size + 0.5f), new Quaternion(0, 0, 0, 0));
                    MapForTrassing[i, k].transform.parent = parent.transform;
                    MapForTrassing[i, k].GetComponent<Scanner>().SetAI(this.gameObject);
                }
        }
        else if (x1 > x2 && z1 < z2)// 3
        {
            vertex1 = new Vector3((int)x1 + FiledExtendet, height, (int)z1 - FiledExtendet);
            vertex2 = new Vector3((int)x1 + FiledExtendet, height, (int)z2 + FiledExtendet);
            vertex3 = new Vector3((int)x2 - FiledExtendet, height, (int)z2 + FiledExtendet);
            // дальше расширяем границы, так чтобы ячеки размером size на size корректно встали
            while (true)
                if ((int)vertex3.x % size == 0)
                    break;
                else
                    vertex3 = new Vector3((int)vertex3.x - 1, height, (int)vertex3.z);
            while (true)
                if ((int)vertex3.z % size == 0)
                    break;
                else
                    vertex3 = new Vector3((int)vertex3.x, height, (int)vertex3.z + 1);
            vertex4 = new Vector3((int)x2 - FiledExtendet, height, (int)z1 - FiledExtendet);
            parent = (GameObject)Instantiate(ScannerPrefab, this.transform.position, new Quaternion(0, 0, 0, 0));
            MapForTrassing = new GameObject[x = (((int)vertex3.z - (int)vertex4.z) / size), y = ((int)vertex1.x - (int)vertex4.x) / size]; // массив точек путей столбцы - строки
            map = new Cell[x, y];
            for (int i = 0; i < x; i++)
                for (int k = 0; k < y; k++)
                    map[i, k] = new Cell();
            for (int i = 0; i < x; i++)
                for (int k = 0; k < y; k++)
                {
                    MapForTrassing[i, k] = (GameObject)Instantiate(ScannerPrefab, new Vector3(vertex4.x + k * size + 0.5f, height, vertex4.z + i * size + 0.5f), new Quaternion(0, 0, 0, 0));
                    MapForTrassing[i, k].transform.parent = parent.transform;
                    MapForTrassing[i, k].GetComponent<Scanner>().SetAI(this.gameObject);
                }
        }
        else if (x1 < x2 && z1 > z2)// 4
        {
            vertex1 = new Vector3((int)x1 - FiledExtendet, height, (int)z1 + FiledExtendet);
            vertex2 = new Vector3((int)x1 - FiledExtendet, height, (int)z2 - FiledExtendet);
            vertex3 = new Vector3((int)x2 + FiledExtendet, height, (int)z2 - FiledExtendet);
            // дальше расширяем границы, так чтобы ячеки размером size на size корректно встали
            while (true)
                if ((int)vertex3.x % size == 0)
                    break;
                else
                    vertex3 = new Vector3((int)vertex3.x + 1, height, (int)vertex3.z);
            while (true)
                if ((int)vertex3.z % size == 0)
                    break;
                else
                    vertex3 = new Vector3((int)vertex3.x, height, (int)vertex3.z - 1);
            vertex4 = new Vector3((int)x2 + FiledExtendet, height, (int)z1 + FiledExtendet);
            parent = (GameObject)Instantiate(ScannerPrefab, this.transform.position, new Quaternion(0, 0, 0, 0));
            MapForTrassing = new GameObject[x = (((int)vertex1.z - (int)vertex2.z) / size), y = ((int)vertex3.x - (int)vertex2.x) / size]; // массив точек путей, [столбцы, строки]
            map = new Cell[x, y];
            for (int i = 0; i < x; i++)
                for (int k = 0; k < y; k++)
                    map[i, k] = new Cell();
            for (int i = 0; i < x; i++)
                for (int k = 0; k < y; k++)
                {
                    MapForTrassing[i, k] = (GameObject)Instantiate(ScannerPrefab, new Vector3(vertex2.x + k * size + 0.5f, height, vertex2.z + i * size + 0.5f), new Quaternion(0, 0, 0, 0));
                    MapForTrassing[i, k].transform.parent = parent.transform;
                    MapForTrassing[i, k].GetComponent<Scanner>().SetAI(this.gameObject);
                }
        }
        delay = Time.deltaTime * 2;
    }


    public void DestroyMapPath()
    {
        GameObject.Destroy(parent);
    }
    #endregion
}


 


Для работы этого скрипта необходимо в инспекторе заполнить три поля, а именно ScannerPrefab, Size (рекомендую ставить число полученное от округления размера коллайдера моба по хFiledExtendet(4-7 - достаточно(СИЛЬНО ВЛИЯЕТ НА ПРОИЗВОДИТЕЛЬНОСТЬ) увеличение необходимо просто для того, чтобы находить путь когда цель находиться прямо по отношению к нам)

Как заполнить целочисленные значения - это понятно =), а ScannerPrefab должен быть заполнен префабом, который можно создать так:
1. Создаем пустой объект назовем его "ScannerPrefab";
2. Надеваем на него BoxCollider;
3. Задаем размеры коллайдеру по x и z ровно такие же как мы указывали в поле Size выше, а y от > 20;
4. BoxCollider переводим в режим триггера;
5. Надеваем Rigidbody, отключаем гравитацию на нем;
6. Ставим скрипт Scanner на него;
7. Ну и наконец заливаем его в префаб и отправляем в поле ScannerPrefab у нашего моба=)

У ScannerPrefab в скрипте Scanner в поле TagsIgnore пишем те теги, которые мы не хотим считать за препятствие, например тег "Terrain"=) Мы же не хотим, чтобы террэин был для нас одним большим препятствием. :(( Самому сканеру тоже дадим тэг, например "Ambience"=) И так же занесем его массив TagsIgnore.

Сам скрипт Scanner (крепим на ScannerPrefab):
Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;

public class Scanner : MonoBehaviour {

    public string[] tagsIgnore; // теги объектов, которые будут игнорироваться при поисик припятствий
    public GameObject AI; // объект породивший этот префаб
    public bool passable;
    public bool on;

    void Start()
    {
        passable = true;
    }
    void OnTriggerStay(Collider c)
    {
        if (!getLisitnse(c.tag) && c.gameObject != AI)
            passable = false;
    }

    public void SetAI(GameObject AI)
    {
        this.AI = AI;
    }

    public void Activated()
    {
        on = true;
    }

    public bool GetON()
    {
        return on;
    }

    public bool GetPassable()
    {
        return passable;
    }

    void OnTriggerEnter(Collider c)
    {
        if (c.gameObject == AI && on == true)
        {
            AI.GetComponent<AI>().NextIndexPath();
        }
    }
    bool getLisitnse(string tag) // Получить разрешение на запрет "passable = true"
    {
        for (int i = 0; i < tagsIgnore.Length; i++)
            if (tagsIgnore[i] == tag)
                return true;
        return false;
    }
}

 


Дальше создадим небольшой мозг для проверки скрипта, банально назовем его "AI". Конечно же этот скрипт часть моба, ему тоже даем Regidbody=)

Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;

public class AI : MonoBehaviour {

    public GameObject aim;
    public Transform[] path; // объекты для передвижения
    public int indexPath;
        void Start () {
        // передадим объект для поиска пути
        this.GetComponent<PathBuilding>().CtreatePath(aim.transform);
        indexPath = -1;
        }

    void Update()
    {
        if (this.GetComponent<PathBuilding>().GetError() == true)
        {
            NextIndexPath();
        }
        else if (this.GetComponent<PathBuilding>().GetComplete() == true)
        {
            path = this.GetComponent<PathBuilding>().GetPath();
            if (path == null)
                NextIndexPath();
            else
                indexPath = path.Length - 1;
        }
        else if (indexPath > -1)
        {
            Movent(2);
            Rotation(path[indexPath].gameObject, 2);
        }
    }


    public void NextIndexPath()
    {
        if (indexPath <= 0)
        {
            this.GetComponent<PathBuilding>().DestroyMapPath();
            GameObject.Destroy(aim);
        }
        else indexPath--;
    }

    private void Rotation(GameObject objectRotation, float speedRotation)
    {
        this.transform.rotation = Quaternion.Slerp(this.transform.rotation, Quaternion.LookRotation(objectRotation.transform.position - this.transform.position), speedRotation * Time.deltaTime);
    }

    private void Movent(float speed)
    {
        this.rigidbody.velocity = transform.TransformDirection(new Vector3(0, 0, (float)speed));
    }
}
 


Так же у скрипта который использует данный поиск пути должен быть открытый метод public void NextIndexPath(), в первое условие при выполнении можно поставить функцию которая будет перезапускать процесс спавна цели до которой мы будем идти. Так же в Scanner's в методе OnTriggerEnter(Collider c) поставим вместо AI название скрипта откуда запускаем процесс поиска.


Хотел спросить:
1. Как можно определить точки касания префаба ScannerPrefab с Terrain'ом, чтобы выровнять их по высоте? Вообщем аккуратно расположить найденные точки по Terrain'у=)

И еще сильно - не пинайте, это мой первый простинький ИИ (полная Ж)
Последний раз редактировалось cyberspace_ru 04 апр 2013, 08:51, всего редактировалось 8 раз(а).
cyberspace_ru
UNец
 
Сообщения: 5
Зарегистрирован: 12 мар 2013, 18:42

Re: Алгоритм обхода препятсвий

Сообщение jetyb 14 мар 2013, 07:18

Мда.. впечатляет. Круто, если все это еще и будет работать.
Код осмысливать нет времени, что особенно бросилось в глаза:

Синтаксис:
Используется csharp
Cell[] AddMassCells(Cell[] mass, Cell cell)
    {
        Cell[] t = new Cell[mass.Length + 1];
        for (int i = 0; i < t.Length; i++)
        {
            if (i != t.Length - 1)
                t[i] = mass[i];
            else t[i] = cell;
        }
        return t;
    }
 

Про списки не слышали? System.Collections.Generic.List

Синтаксис:
Используется csharp
Cell GetBeginCell() // получить начальную точку
    {

        for (int i = 0; i < x; i++)
            for (int k = 0; k < y; k++)
                if (map[i, k].begin == true)
                    return map[i, k];
        return null;
    }
 

А не проще ли хранить begin и end не как свойства ячеек, а в виде координат ячейки в массиве?

Как можно определить точки касания префаба ScannerPrefab с Terrain'ом, чтобы выровнять их по высоте?

http://docs.unity3d.com/Documentation/S ... eight.html
jetyb
Адепт
 
Сообщения: 1486
Зарегистрирован: 31 окт 2011, 17:21

Re: Алгоритм обхода препятсвий

Сообщение cyberspace_ru 14 мар 2013, 11:44

jetyb писал(а):Мда.. впечатляет. Круто, если все это еще и будет работать.


Все работает, можете в этом сами убедиться =) Главное быть внимательным к игнорируемым тегам, иначе все поле будет непроходимо.
И в коде прежде чем забирать массив, посмотреть "Создан ли путь?"
Синтаксис:
Используется csharp
this.GetComponent<PathBuilding>().GetComplete()

"И нет ли ошибок?"
Синтаксис:
Используется csharp
this.GetComponent<PathBuilding>().GetError()

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

jetyb писал(а):А не проще ли хранить begin и end не как свойства ячеек, а в виде координат ячейки в массиве?

Не проще, я хотел сделать ячейки как автономное хранилище, чтобы унифицировать их под другие алгоритмы поиска.

Процесс выглядит так:
Изображение
и после поиска не нужные "сканеры" удаляются, остальные передаются в виде массива где path[0] - конечная точка, а path[path.Length - 1] - начало пути.


Изображение

Спасибо за ответ!=)
cyberspace_ru
UNец
 
Сообщения: 5
Зарегистрирован: 12 мар 2013, 18:42

Re: Алгоритм обхода препятсвий

Сообщение cyberspace_ru 14 мар 2013, 14:44

Итог проделанной работы:
Построенный маршрут
Изображение
Изображение
cyberspace_ru
UNец
 
Сообщения: 5
Зарегистрирован: 12 мар 2013, 18:42

Re: Алгоритм обхода препятствий

Сообщение beatlecore 02 фев 2014, 11:24

Поделитесь наработками
Аватара пользователя
beatlecore
Старожил
 
Сообщения: 964
Зарегистрирован: 05 фев 2013, 21:26
Откуда: Sun Crimea


Вернуться в Искуственный Интеллект

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2