Поиск путей. Ошибка в алгоритме.

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

Поиск путей. Ошибка в алгоритме.

Сообщение Medveckij 10 янв 2013, 01:21

Товарищи милые люди :)

Проблема вот в чем...

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

Позавчера переписывался с автором скрипта и да, он сам подтвердил, что проблема существует, но решить он ее так и не смог. Потому продолжает кормить публику ломаным продуктом. - http://www.youtube.com/watch?v=i3HunQfX ... re=mh_lolz

В данной ссылке он описывает сам алгоритм, который на первый взгляд кажется рабочим.

Уже как несколько дней пытаюсь починить скрипт, но все безуспешно.

Возможно Наши монстры в состоянии вылечить сие творение? Из последних сил пытался сделать все сам, но как видите не вышло.

Снял маленькое видео с акцентом на глюк:




на всякий пожарный ссылка на видео: http://www.youtube.com/watch?v=kBiTUOZW ... e=youtu.be







А вот и сам проект с разложенными скриптами по полочкам. - (FPS1.33.zip)

http://forum.unity3d.com/threads/127273 ... post858624


Очень надеюсь на вашу помощь. Зарание бесконечное спасибо на всех языках галактики!

P.S. Если вдруг причина нежелания помочь будет заключаться в JS, я с радостью перепишу все на C#. Только cкажите :ympeace:


На всякий случай дополнительно прикрепляю скрипты.

AIpathCellScript

Синтаксис:
Используется javascript

var doors = new Array();


function OnTriggerEnter (other : Collider)
{
        if (other.tag == "AIpathDoor"){
                doors.Add(other.gameObject);
                }
}



 



AIpathDoorScript

Синтаксис:
Используется javascript

var cells = new Array();
var doorsToCells = new Array();
var imediateCells = new Array();
var testForCells : boolean = true;
var waitToTestCells : float = 2;
var stage : int = 1;

@HideInInspector
var doorOpen : boolean = true;

function Awake ()
{
        doorOpen = true;
        cells = GameObject.FindGameObjectsWithTag("AIpathCell");
        doorsToCells.length = cells.length;
        testForCells = true;
        waitToTestCells = 2;
        stage = 1;
}

function Update ()
{
        if (testForCells && waitToTestCells <= 0)
        {
                for (var imediateCell : GameObject in imediateCells)
                {
                        for (var i : int = 0; i <= cells.length - 1; i++)
                        {
                                if (cells[i] == imediateCell)
                                        doorsToCells[i] = 1;
                        }
                }
               
                for (stage = 2; stage <= cells.length; stage++)
                {
                        for (i = 0; i <= cells.length - 1; i++)
                        {
                                if (doorsToCells[i] == stage - 1)
                                        for (var checkDoor : GameObject in cells[i].GetComponent(AIpathCellScript).doors)
                                        {
                                                if (checkDoor != gameObject)
                                                {
                                                        for (var checkCell : GameObject in checkDoor.GetComponent(AIpathDoorScript).imediateCells)
                                                        {
                                                                for (var j : int = 0; j <= cells.length - 1; j++)
                                                                {
                                                                        if (cells[j] == checkCell && doorsToCells[j] == null)
                                                                                doorsToCells[j] = stage;
                                                                }
                                                        }
                                                }
                                        }
                        }
                }
               
                testForCells = false;
                Debug.Log(doorsToCells);
        }
        waitToTestCells -= 1;
}

function OnTriggerEnter (other : Collider)
{
        if (other.tag == "AIpathCell")
                imediateCells.Add(other.gameObject);
}

 



PlayerMovementScript

Синтаксис:
Используется javascript

function OnTriggerStay (hitTrigger : Collider)
{

    if(hitTrigger.tag == "AIpathCell")
    currentCell = hitTrigger.gameObject;

 



EnemyMovementScript

Синтаксис:
Используется javascript

var playerCell : GameObject; //

var goalDoor : GameObject; //

var shortestPathSoFar : float; //

@HideInInspector

var waitToStart : int = 5;

var currentMoveSpeed : float = 5;

var lastCell : GameObject;

 

function Awake ()

{

    shortestPathSoFar = Mathf.Infinity;

    playerMovementScript = GameObject.FindWithTag("Player").GetComponent(PlayerMovementScript);
   
    playerTransform = GameObject.FindWithTag("Player").transform;

    waitToStart = 5;

}

 

function Update ()

{

    if(waitToStart <= 0 && (currentCell != lastCell || playerCell != playerMovementScript.currentCell))

    {
   
        lastCell = currentCell;

        playerCell = playerMovementScript.currentCell;

        for (var doorCheckingNow : GameObject in currentCell.GetComponent(AIpathCellScript).doors)

        {

            for (var i : int = 0; i <= doorCheckingNow.GetComponent(AIpathDoorScript).cells.length - 1; i++)

            {

                if (doorCheckingNow.GetComponent(AIpathDoorScript).cells[i] == playerCell)

                if (doorCheckingNow.GetComponent(AIpathDoorScript).doorsToCells[i] < shortestPathSoFar)

                {

                    goalDoor = doorCheckingNow;

                    shortestPathSoFar = doorCheckingNow.GetComponent(AIpathDoorScript).doorsToCells[i];

                }

            }

        }

        shortestPathSoFar = Mathf.Infinity;
    }

    waitToStart -= 1;
   
   
    if(goalDoor && currentCell != playerCell)
    transform.position += (goalDoor.transform.position - transform.position).normalized * currentMoveSpeed * Time.deltaTime;

   
    if(playerCell == currentCell)
    transform.position += (playerTransform.position - transform.position).normalized * currentMoveSpeed * Time.deltaTime;
   
   

     
}

 

function OnTriggerEnter (hitTrigger : Collider)

{

    if (hitTrigger.tag == "AIpathCell")

        currentCell = hitTrigger.gameObject;

}

 
Аватара пользователя
Medveckij
Адепт
 
Сообщения: 1014
Зарегистрирован: 10 ноя 2012, 15:44

Re: Поиск путей. Ошибка в алгоритме.

Сообщение IDoNotExist 10 янв 2013, 05:32

Medveckij писал(а):P.S. Если вдруг причина нежелания помочь будет заключаться в JS, я с радостью перепишу все на C#. Только cкажите :ympeace:

Причина нежелания помочь будет заключаться в том, что никто не захочет ковыряться в чужом говнокоде написанном непонятно кем.
Зачем вы вообще скачиваете всякий треш, да еще тем более написанный на JS и еще пытаетесь в нем разобраться, в Asset Store полным полно же нормальных бесплатных проектов в этом направлении, я уже молчу про встроенный поиск путей.
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1432
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Поиск путей. Ошибка в алгоритме.

Сообщение AndreyMust19 10 янв 2013, 13:13

в Asset Store полным полно же нормальных бесплатных проектов

Если бы это действительно было так, никто бы не писал свой поиск пути.

Из видео понятно что при выходе игрока из зоны, если кубик находится на границе двух комнат попадает в неопределенное состояние, когда не знает что нужно делать. А возможно он просто пытается двигаться в 1 комнату, затем во 2-ю, затем снова в первую и т. д.
Мне не совсем понятно зачем здесь "двери". Если комнаты - вершины, а связи - ребра, то связь между 2-мя комнатами можно определять просто пересечением комнат.
Обратите внимание сюда:
Синтаксис:
Используется javascript
if (goalDoor && currentCell != playerCell)
transform.position += (goalDoor.transform.position - transform.position).normalized * currentMoveSpeed * Time.deltaTime;
if(playerCell == currentCell)
transform.position += (playerTransform.position - transform.position).normalized * currentMoveSpeed * Time.deltaTime;


Что будет если (goalDoor == null && currentCell != playerCell) ? Ничего не будет, кубик останется стоять на месте. Мне кажется, что именно это и происходит при глюке. Добавьте еще одно условие или напишите этот участок так, чтобы кубик в любом случае куда-нибудь да двигался.
Для отладки заведите public enum и записывайте в него название текущего состояния кубика (идти в другую комнату, идти к игроку, ...), только каждый Update сбрасывайте ее значение. В момент глюка посмотрите через инспектор значение этой переменной.
Нужна помощь? Сами, сами, сами, сами, сами... делаем все сами
AndreyMust19
Адепт
 
Сообщения: 1119
Зарегистрирован: 07 июн 2011, 13:19

Re: Поиск путей. Ошибка в алгоритме.

Сообщение Medveckij 10 янв 2013, 16:05

AndreyMust19 писал(а):
в Asset Store полным полно же нормальных бесплатных проектов

Если бы это действительно было так, никто бы не писал свой поиск пути.

Из видео понятно что при выходе игрока из зоны, если кубик находится на границе двух комнат попадает в неопределенное состояние, когда не знает что нужно делать. А возможно он просто пытается двигаться в 1 комнату, затем во 2-ю, затем снова в первую и т. д.
Мне не совсем понятно зачем здесь "двери". Если комнаты - вершины, а связи - ребра, то связь между 2-мя комнатами можно определять просто пересечением комнат.
Обратите внимание сюда:
Синтаксис:
Используется javascript
if (goalDoor && currentCell != playerCell)
transform.position += (goalDoor.transform.position - transform.position).normalized * currentMoveSpeed * Time.deltaTime;
if(playerCell == currentCell)
transform.position += (playerTransform.position - transform.position).normalized * currentMoveSpeed * Time.deltaTime;


Что будет если (goalDoor == null && currentCell != playerCell) ? Ничего не будет, кубик останется стоять на месте. Мне кажется, что именно это и происходит при глюке. Добавьте еще одно условие или напишите этот участок так, чтобы кубик в любом случае куда-нибудь да двигался.
Для отладки заведите public enum и записывайте в него название текущего состояния кубика (идти в другую комнату, идти к игроку, ...), только каждый Update сбрасывайте ее значение. В момент глюка посмотрите через инспектор значение этой переменной.




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

Не совсем так. И зеленые зоны и синие двери в данном случае являются триггерами. Player заходит в первую зону (a), зона (a) становится "playerCell". В то время как Enemy находится в зоне (b) - currentCell. currentCell != playerCell = Enemy двигается к двери которая находится ближе к playerCell.
Войдя в последнюю дверь Enemy соприкасается с зоной на которой стоит Player. Выходит, что теперь if(playerCell == currentCell) = Enemy преследует Player`a напрямую, пока тот не перейдет в другую зону. Тогда все начинается сначала.

Проблема в том, что зона (a) и к примеру зона (b) соприкасаются друг с другом и в то время, когда Enemy находится на границе playerCell, его currentCell сходится с playerCell, но ведь в это же время он все еще находится на границе между зонами и потому если в этот момент резко увести Player`a из своей зоны,
то зона из которой Только Что пришел Enemy и на границе которой он находится превратится в playerCell, а зона в которую Enemy как бы шел останется currentCell. Выходит что на границе между (a) и (b) Enemy не сходится со сценарием и следующий скрипт if(playerCell == currentCell) не может осуществиться. Взамен нашему Enemy предлагают следующий вариант - if(goalDoor && currentCell != playerCell) = иди ка ты в двери. Он и идет в двери, там и застревает.

Попробовал вставить костыль и во время пересечения границ как бы Вытягивать Enemy из мертвой точки за собой на 2-5. Чтобы его currentCell сошелся с playerCell, но нет, не работает. Как только дистанция увеличивается Enemy возвращается в двери.

Синтаксис:
Используется javascript

  var dist = Vector3.Distance(playerTransform.position, transform.position);//
   
    if(goalDoor && currentCell != playerCell && dist>=10)
    transform.position += (goalDoor.transform.position - transform.position).normalized * currentMoveSpeed * Time.deltaTime;
    else
    {
    transform.position += (playerTransform.position - transform.position).normalized * currentMoveSpeed * Time.deltaTime;
    }

 



Вообщем, караул!
Последний раз редактировалось Medveckij 10 янв 2013, 16:18, всего редактировалось 1 раз.
Аватара пользователя
Medveckij
Адепт
 
Сообщения: 1014
Зарегистрирован: 10 ноя 2012, 15:44

Re: Поиск путей. Ошибка в алгоритме.

Сообщение Medveckij 10 янв 2013, 16:13

IDoNotExist писал(а):
Medveckij писал(а):P.S. Если вдруг причина нежелания помочь будет заключаться в JS, я с радостью перепишу все на C#. Только cкажите :ympeace:

Причина нежелания помочь будет заключаться в том, что никто не захочет ковыряться в чужом говнокоде написанном непонятно кем.
Зачем вы вообще скачиваете всякий треш, да еще тем более написанный на JS и еще пытаетесь в нем разобраться, в Asset Store полным полно же нормальных бесплатных проектов в этом направлении, я уже молчу про встроенный поиск путей.



Не надо много. Приведите Один бесплатный пример.

встроенный поиск путей не подходит.
Аватара пользователя
Medveckij
Адепт
 
Сообщения: 1014
Зарегистрирован: 10 ноя 2012, 15:44

Re: Поиск путей. Ошибка в алгоритме.

Сообщение AndreyMust19 10 янв 2013, 17:40

Тогда решите проблему из-за которой кубик может находиться сразу в двух комнатах (currentCell). Объект не может находится в двух местах сразу, пусть после пересечения с новым триггером кубик забудет про предыдущую комнату.
Нужна помощь? Сами, сами, сами, сами, сами... делаем все сами
AndreyMust19
Адепт
 
Сообщения: 1119
Зарегистрирован: 07 июн 2011, 13:19

Re: Поиск путей. Ошибка в алгоритме.

Сообщение Medveckij 10 янв 2013, 22:42

AndreyMust19 писал(а):Тогда решите проблему из-за которой кубик может находиться сразу в двух комнатах (currentCell). Объект не может находится в двух местах сразу, пусть после пересечения с новым триггером кубик забудет про предыдущую комнату.


Нет, не помогло. Не понимаю в чем дело. Запутался окончательно.

Ребят, форум полон монстров для которых решение подобной задачи как два пальца об асфальт. Что, так сложно помочь?
Аватара пользователя
Medveckij
Адепт
 
Сообщения: 1014
Зарегистрирован: 10 ноя 2012, 15:44

Re: Поиск путей. Ошибка в алгоритме.

Сообщение IDoNotExist 11 янв 2013, 05:12

Medveckij писал(а):Не надо много. Приведите Один бесплатный пример.

встроенный поиск путей не подходит.

A* pathfinding
Вполне достойный проект, много положительных отзывов, сам пользовался им давным давно, бесплатной версией, когда проект был еще в бета версии и его даже не было на Asset Store, он вполне подошел под мои задачи.
Ссылка на Free версию
Аватара пользователя
IDoNotExist
Адепт
 
Сообщения: 1432
Зарегистрирован: 23 мар 2011, 09:18
Skype: iamnoexist

Re: Поиск путей. Ошибка в алгоритме.

Сообщение AndreyMust19 11 янв 2013, 07:50

Допишите свои скрипты чтобы в них не было необъявленных переменных. И перестаньте все время вызывать GetComponent, сохраните в ссылку!
Нужна помощь? Сами, сами, сами, сами, сами... делаем все сами
AndreyMust19
Адепт
 
Сообщения: 1119
Зарегистрирован: 07 июн 2011, 13:19

Re: Поиск путей. Ошибка в алгоритме.

Сообщение Medveckij 11 янв 2013, 18:59

IDoNotExist писал(а):
Medveckij писал(а):Не надо много. Приведите Один бесплатный пример.

встроенный поиск путей не подходит.

A* pathfinding
Вполне достойный проект, много положительных отзывов, сам пользовался им давным давно, бесплатной версией, когда проект был еще в бета версии и его даже не было на Asset Store, он вполне подошел под мои задачи.
Ссылка на Free версию



встроенный поиск путей не подходит.


Смысл использовать пакет со скриптами в 3 тысячи строчек? Совершенно не ясно как оно работает. Применить не проблема, но плохо когда ты не контролируешь ход событий. Не дай бог что нибудь упадет, сиди потом и думай о чем все эти люди.
Аватара пользователя
Medveckij
Адепт
 
Сообщения: 1014
Зарегистрирован: 10 ноя 2012, 15:44

Re: Поиск путей. Ошибка в алгоритме.

Сообщение seaman 11 янв 2013, 19:56

Смысл использовать пакет со скриптами в 3 тысячи строчек?

Тогда зачем Вы используете Юнити. В нем куда больше строчек. Пишите свой движок, если хотите все контролировать!
Ну вот зачем придумали библиотеки? Чтобы не изобретать велосипед!
Посмотрите, вроде то-то похожее.Может поможет:
Статейка
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

Re: Поиск путей. Ошибка в алгоритме.

Сообщение Medveckij 11 янв 2013, 21:44

seaman писал(а):
Смысл использовать пакет со скриптами в 3 тысячи строчек?

Тогда зачем Вы используете Юнити. В нем куда больше строчек. Пишите свой движок, если хотите все контролировать!
Ну вот зачем придумали библиотеки? Чтобы не изобретать велосипед!
Посмотрите, вроде то-то похожее.Может поможет:
Статейка



Вроде похоже, да. Проштудирую.

Библиотеки это конечно хорошо, но не дай бог завтра или через год c Unity что-нибудь случится. Сидит программер на пеньке и вспоминает былые времена, как хорошо он умел использовать готовые пакеты. Если вы мозг и быстренько пролестав script (3к строчек) в состоянии понять о чем он и как его починить в случае падения, моя шляпа у ваших ног. Мне же до подобного пока далеко. Потому пока я просто не могу позволить себе использовать подобные пакеты. Пусть Хуже, пусть в 100 раз хуже, но мое и я знаю как с этим работать.

За ссылку спасибо
Аватара пользователя
Medveckij
Адепт
 
Сообщения: 1014
Зарегистрирован: 10 ноя 2012, 15:44

Re: Поиск путей. Ошибка в алгоритме.

Сообщение Multirezonator 12 янв 2013, 08:34

Medveckij писал(а):Пусть Хуже, пусть в 100 раз хуже, но мое и я знаю как с этим работать.

Смотрю я на свои скрипты через 3 месяца: и оформленно все четко, и названия переменных вменяемые и комментарии присутствуют, а чтобы разобраться как работают - нужно время, и немало...
Скрытый текст:



Аватара пользователя
Multirezonator
UNITрон
 
Сообщения: 248
Зарегистрирован: 15 фев 2010, 16:12
Откуда: Украина, Луганск
  • Сайт

Re: Поиск путей. Ошибка в алгоритме.

Сообщение AndreyMust19 12 янв 2013, 12:44

Любому коду нужна сопроводительная документация, особенно в плане интерфейса - какую функцию вызывать и что каждый параметр означает. Составлять документацию прямо в комментариях - грех, получается салат из кода и технической документации.
Нужна помощь? Сами, сами, сами, сами, сами... делаем все сами
AndreyMust19
Адепт
 
Сообщения: 1119
Зарегистрирован: 07 июн 2011, 13:19


Вернуться в Почемучка

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

Сейчас этот форум просматривают: Google [Bot], Yandex [Bot] и гости: 20