Поиск и заполнение грида . Зависание при цикличной повторной проверке. Unity
У меня есть поле из квадратов. Мне надо что бы алгоритм проверил поле и следом соседние поля от выбранного грида и заполнял ( вправо или влево) до окончания.
Сразу прошу сильно не бить из за рефакторинга. Я только учусь.Пришлось как то разбить код.
Проблема заключается в чём. При обработке этого кода Unity просто зависает.Думаю из за того что программа не имеет окончания из за цикла в void FillPath. Помогите разобраться как правильно запустить проверку? что бы избежать( зависания и цикла). Или что б цикл окончился после проверки последнего элемента.
void Search (GameObject[] EarthObjectsAll, Stack<GameObject> myStackPath, Vector3[] TestCoord1,
Stack<Vector3> mySosedStack, Vector3[] TestCoord, Stack<GameObject> myRecursiveStack) {
// перебор объектов стака пути
foreach (GameObject O in myStackPath) {
// замена всех объектов пути на землю
Instantiate(EarthObject, O.transform.position, Quaternion.identity);
}
// запускаю алгоритм заполнения
FillPath(EarthObjectsAll, mySosedStack, myRecursiveStack, EarthTagObjectsAll);
// возвращаю индикатор окончания пути в нормальное состояние
PassEndsIndenti = true;
}
Алгоритм пошагового заполнения.
void FillPath (GameObject[] EarthObjectsAll, Stack<Vector3> mySosedStack, Stack<GameObject> myRecursiveStack, GameObject[] EarthTagObjectsAll) {
// переберем все объекты поля
foreach (GameObject D in EarthObjectsAll) {
// получаем координаты объекта
Vector3 ObjectPosition = D.transform.position;
// переберем объекты соседей
foreach (Vector3 V in mySosedStack) {
//сравниваем позиции
if (ObjectPosition.Equals(V)) {
// заполнение соседей
Instantiate(EarthObject, ObjectPosition, Quaternion.identity);
// координаты для генерации следующих соседей и их заливки
myRecursiveStack.Push(D);
}
}
}
//обнуляет стак соседей
mySosedStack = new Stack<Vector3>();
//Перебираю
foreach (GameObject L in myRecursiveStack) {
//Генерирую координаты соседей
GenCoordsMet(L, TestCoord, mySosedStack);
}
// Запускаю алгоритм заново
FillPath(EarthObjectsAll, mySosedStack, myRecursiveStack, EarthTagObjectsAll);
}
Добавляю в стак для последующей цикличной обработки mySosedStack.
void GenCoordsMet (GameObject thatObgect, Vector3[] TestCoord, Stack<Vector3> mySosedStack) {
// координаты объекта земли
Vector3 Pozition = thatObgect.transform.position;
// наполнение массива координатами соседей
TestCoord = GenCoordTest(Pozition);
//Добавление координат объектов для следующего шага
foreach (Vector3 G in TestCoord) {
// создает следующий шаг соседей
mySosedStack.Push(G);
}
}
Генерирую координаты по оси Х
Vector3[] GenCoordTest (Vector3 T) {
// объявим массив из 4 точек
Vector3[] S = new Vector3[1];
//правая точка(координаты справа)
S[0] = T; S[0].x++;
return S;
}
Ответы (2 шт):
В конце метода FillPath ты вызываешь ещё один FillPath (это называется рекурсия).
Второй метод вызывает третий и т.д. до бесконечности подобно циклу while (true) {}.
Команда return; остановит выполнение даже void метода и необходимо добавить условие для конца цикла.
Итак я пошел другим путём. Спасибо Yaroslav навел меня на мысль. Спасибо Bulson за идею отладки.
Немного по шаманив убрал путаницу и с отладкой и переписав код.Я все таки добился нужного эффекта. Вставляю части кода может кому пригодиться . Кому интересно что я Творю или если есть идеи как это дело всё улучшить . Буду рад поделиться ссылкой на гитхаб и если что буду рад научиться чему то новому.
if (PassEndsIndenti == false)// при остановке запускаю скрипт замены всех тайтлов пути на тайтлы земли
{
foreach (GameObject O in myStackPath)// перебор объектов стека пути
{
Debug.Log(myStackPath.Count + "myStackPath.Count");
Vector3 Pozition = O.transform.position;// координаты объекта земли
TestCoord = GenCoordTest(Pozition);// наполнение массива координатами соседей
foreach (Vector3 T in TestCoord) Debug.Log(T + "TestCoord1");// Координаты соседей
Debug.Log(TestCoord.Length + "TestCoord.Length 1");
foreach (Vector3 G in TestCoord)
{
myVectorSosedStack.Push(G); // создает следующий шаг соседей
}
}
NewMethod();
myVectorSosedStack = new Stack<Vector3>();//обнуляем стек
myStackPath = new Stack<GameObject>();//обнуляем стек
PassEndsIndenti = true;// возвращаю индикатор окончания пути в нормальное состояние
}
Идея кода сверху. При команде "PassEndsIndenti=false" при остановке запускаю скрипт замены всех тайтлов пути на тайтлы земли.И в последствии генерирую координаты соседей добавляя их в стек для проверки. И далее запускаем метод заливки NewMethod().
void NewMethod()
{
foreach (Vector3 V in myVectorSosedStack)// переберем объекты соседей
{
foreach (GameObject D in ObjectsAll)// переберем все объекты в ObjectsAll
{
Vector3 ObjectPosition = D.transform.position;// получаем координаты объекта
if (ObjectPosition == V)//сравниваем позиции
{
Instantiate(PathObject, ObjectPosition, Quaternion.identity);// заполнение соседей
Debug.Log(ObjectPosition + "ObjectPosition");
foreach (GameObject W in myStackAllEarthBlockObject)// проверяем объекты myStackAllEarthBlockObject
{
Vector3 blockPosition = W.transform.position;
if (blockPosition == ObjectPosition) //если объект который сгенерировался упёрся в другой объект
{
Debug.Log("ObjectPosition == blockPosition");
AAAA = true;// Затычка для блокировка следующего когда если ObjectPosition == blockPosition
break;
}
}
if (AAAA != true)
{
Тут часть можно заменить на метод кому не лень.От сюда ...
TestCoord = new Vector3[] { };
myVectorSosedStack = new Stack<Vector3>();
Vector3 Pozition = D.transform.position;// координаты объекта земли
TestCoord = GenCoordTest(Pozition);// наполнение массива координатами соседей
foreach (Vector3 G in TestCoord)
{
myVectorSosedStack.Push(G);
}
До
NewMethod();//перезапускаем метод заливки
}
// Debug.Log("ObjectPosition != blockPosition");
break;// прерываем поиск
}
}
}
AAAA = false;// возвращаем значение для последующих повторений кода .
}