Войти
ПрограммированиеФорумГрафика

Проверка свободного места в пространстве Unity

Страницы: 1 2 Следующая »
#0
(Правка: 19 янв 2023, 1:36) 19:21, 18 янв 2023

Есть генератор бесконечной прямой трассы (с заданной шириной) состоящей из кубов. Над каждым кубом, случайным образом, может сгенерироваться препятствие размером в 1 куб или больше (1х3, 2х2, ...) из указанного списка. Проблема в том, чтобы не генерировать препятствие внутри другого.

Генерация происходит следующим образом (слева направо, от игрока вдаль):
1) устанавливается стартовая позиция
2) генерация куба на стартовой позиции
3) проверка свободного места над кубом
4) проверка шанса на генерацию препятствия
5) генерация препятствия
6) смещение стартовой позиции
7) к 2 шагу

Препятствие ставиться левым ближним углом над кубом когда прокнул шанс спавна.

Я реализовал проверку через дополнительный коллайдер, который ставиться над последним сгенерированным кубом (transform.position) и меняет свой тег в случае коллизии (OnCollisionEnter - tag = "Busy", OnCollisionExit - tag = "Free"). При генерации препятствия проверяется тег коллайдера. НО КОЛЛАЙДЕР МЕНЯЕТ СВОЙ ТЕГ 3 РАЗА И ВСЕ.
Потом сделал переменную areaIsFree и глобальный доступ к ней в проверочном коллайдере. Но оказалось, что коллизия работает вообще невпопад и смысла от areaIsFree нету (препятствия спавняться внутри друг друга). На проверочном коллайдере есть RigidBody (с ним и без, кинематик или нет) который не влияет на результат, по крайней мере работает не так как задумано. Проверочный коллайдер имеет тот же слой что и препятствие.
Пробовал вместо OnCollisionEnter OnTriggerEnter, но безуспешно.

Почему в этом случае колизи работают так плохо?
Как еще можно реализовать проверку свободного места?

private void SetRoadRow()
    {
        /*incruises difficulty by obstaclesSpawnrateBoost per 1000 score points*/
        float difficultiUP = ScoreCounter.Counter.GetScore() * obstaclesPerBlok * obstaclesSpawnrateBoost / 1000; 
        
        for (int x = 0; x < width; x++)
        {
            curPos.Set(curPos.x + cubeEdgeLenght, curPos.y, curPos.z);
            SpawnArea.SArea.transform.position = curPos + new Vector3(0, cubeEdgeLenght + 0.1f, 0);
            SetObject(curPos, (int)ObjectName.RoadBlock);
 
            if(SpawnArea.SArea.areaIsFree)
            {
                if (UnityEngine.Random.value < lungeChrgePerBlok)
                    SetLungeCharge(curPos);
                else if (UnityEngine.Random.value < obstaclesPerBlok + difficultiUP)
                    SetObstacle(curPos, x);
            }
                
 
        }
        curPos.Set(startPos.x, curPos.y, curPos.z + cubeEdgeLenght);
    }
 
 
public class SpawnArea : MonoBehaviour
{
    public static SpawnArea SArea { get; set; }
    public bool areaIsFree = true;
 
    private void Awake()
    {
        SArea = this;
    }
    private void OnCollisionEnter(Collision collision)
    {
        areaIsFree = false;
        Debug.Log("coll in: "+transform.position);
        //gameObject.tag.Equals("Busy");
        //Debug.Log(gameObject.tag);
    }
    private void OnCollisionExit(Collision collision)
    {
        areaIsFree = true;
        Debug.Log("coll OUT: " + transform.position);
        //gameObject.tag.Equals("Free");
        //Debug.Log(gameObject.tag);
    }
}

P.S.
Так выглядит генерация препятствий 2х2 (вот эти большие плиты не должны пересекаться)
Screenshot | Проверка свободного места в пространстве Unity

#1
23:45, 18 янв 2023

Ну вы точно знаете, где у вас что стоит (есть координаты центров кубов). Что мешает смещаться при генерации нового на минимально требуемую дистанцию? Если вы его спавните не ровно а под наклоном, тогда нужно учитывать ширину в иной проекции, как прямо.

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

коллизия работает вообще невпопад

Если коллизия работает невпопад, значит у вас 100% ошибка где-то.

#2
0:07, 19 янв 2023

FourGen
> 100% ошибка где-то.
+
FourGen
насколько я его понял он спавнит препятствия на трассе рандомно, но не понял как так они могут друг в друге оказаться, можно по идее сделать больше расстояние между ними.
Тут бы илюстрацию что бы мы написали код за него, а он потом выложил игру и заработал за нас денег хех.

> Еще вариант, это пускать луч
Кстати что там с кастами у юнити, нормально они работают через физику ?
Раньше читал хейт на эту тему, а потом что юнитеки это поправили.Есть где гайд на эти темы ?

#3
0:32, 19 янв 2023

>endeavour_pr
Да вроде шикарно работают. Тестил на тормознутость... 1к в упдейте подлагивает прилично у меня, но их и не нужно столько, как и апдейт сам.

#4
(Правка: 0:42) 0:41, 19 янв 2023

FourGen
> подлагивает прилично у меня, но их и не нужно столько, как и апдейт сам.
ну вот обджекты проверять на столкновения при спавне
в анриле на принтах есть тупа чекбоксы, на плюсах не смотрел но думаю также, хз как работает.
А в юнити приходится голову ломать, а если объктов много ?
Можно в обычном апдейте их использовать не в физичном ?
Или ломать голову над орхитектурой, что бы оно выдавливалось из пула и как то считалось заранее где занятые места а где свободные, что тоже можно сделать, но хз как быстро это будет работать если их много.
А если я захочу сделать ховерборд парящий на рейкастах ?

#5
1:08, 19 янв 2023

Ну у меня движение на рейкастах проблем нет вроде, думаю с ховербордом проблем не будет так же.

Можно в обычном апдейте их использовать не в физичном ?

Я вообще апдейт не использую. Так что не знаю. Так же не знаю видов апдейтов. Вроде он 1.

#6
(Правка: 2:05) 2:03, 19 янв 2023

FourGen
> Так же не знаю видов апдейтов. Вроде он 1.
да там есть несколько

Update
LateUpdate
FixedUpdate

#7
(Правка: 18:11) 17:06, 19 янв 2023

>Qwerqe
Вот с картинкой более понятно. Могу со 100% уверенностью заявить, что вы их ставите почти "от балды". Так как у вас оно все же идет без всяких наклонов, то все проще значительно. Я сам сейчас примерно этим и занимаюсь.
Для решения вопроса требуется правильно считать координаты - это самый правильный вариант и более простой.

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

Например квадрат размером 1 x 1
 (-0.5, 0.5)        (0.5, 0.5)
                *--—*
                |   |
                *-—-*
(-0.5, -0.5)        (0.5, -0.5)

Что бы добавить в нижний левый угол надо вычесть, что бы в верхний прибавить ну и тд.

Предположу, что косяк в этом или в рендоме.

Почему в этом случае колизи работают так плохо

К стати вопрос, а коллайдеры и коллизии не дадут один объект в другой поставить? (только заметил.) Объекты то вы же ставите. Проверили, посчитали, что правильно, поставили, а оно не правильно.

Вот вроде ничего не перекрывает и ставится с рендомным смещением
Blocks | Проверка свободного места в пространстве Unity

+ Показать


>endeavour_pr
А вы про это, да такое видел, ну на камере я вроде использую LateUpdate, но я разницы не заметил, до кадра после кадра один фиг с виду.
А фиксированный да его только и использую.

#8
19:56, 21 янв 2023

FourGen
Самое простое для проверки занятого места - триггерами. Они в юньке тоже быстро работают и в целом корректно отрабатывают геометрию.

#9
20:50, 21 янв 2023

Qwerqe
> Как еще можно реализовать проверку свободного места?

Physics.CheckBox
Physics.BoxCast
и т.п. (сфера вместо бокса)

Они проверяют, нет ли коллайдеров в заданном объеме пространства.

Qwerqe
> Я реализовал проверку через дополнительный коллайдер, который ставиться над
> последним сгенерированным кубом

Можно вообще без коллайдеров. Прицепить к кубу скрипт, в переменную которого записывать, установлено ли там препятствие. И перед установкой нового препятствия это свойство проверять.

#10
(Правка: 2:27) 2:20, 22 янв 2023

>sledo
Для триггеров нужен ритжитбади, как я понял.
Как только я добавляю 1 риджитбади на объект в сцене фпс падает на 100 примерно из 300, а работают они может и быстро, но я не заметил.

Я к чему... ну есть 100, 200, 300 значений... проблема их проверить и посчитать какие следующие удалив при этом не нужные? Зачем какие-то извращения с колалйдерами или теми же рейкастами, о каких я
ниписал выше.

в клетке 1 стоит объект... можно ли ставить объект в клетку 1?

>Virtex
Проверять как?

#11
(Правка: 6:22) 6:09, 22 янв 2023

FourGen
> Для триггеров нужен ритжитбади, как я понял.
там в обработке коллизий есть коллайдер, а есть тригер
вот для какого то из них можно приделать ригид в режиме кинематика и включив на коллайдере is trigger, т.е. костыль для того что бы физический движок обрабатывал.
Вроде так, сам периоидчески забываю эти костыли если не пользуюсь.
А кто то вообще свою физику пишет ) или свою систему по типу воксельной навигации.

#12
(Правка: 12:11) 12:04, 22 янв 2023

>endeavour_pr

т.е. костыль для того что бы физический движок обрабатывал

Ну как вариант так можно сделать. Но дальше то что будет?
Поставили 1 на другой, сработал триггер, определили это событие. Или использовали BoxCast, ну есть коллизия...
Что далее делаем?
Двигаем куда? Вверх? вниз, по диагонали? Если не знаем куда надо двигать? Получаем точку коллизии и пресчитываем координаты и сдвигаем на эту дельту, а если 3 точки коллизии или 10 точек? Так проще сразу посчитать, чем ставить проверять и потом двигать.

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

p.s
Нет, конечно, если стоит вопрос именно в проверке свободного места, то вот Virtex написал по мне так самый правильный вариант.

#13
(Правка: 12:12) 12:11, 22 янв 2023

FourGen
> Или использовали BoxCast, ну есть коллизия...
мне кажется лучше делать это.

FourGen
> Двигаем куда? Вверх? вниз, по диагонали?
фейл, потому что коллизии не подходят для телепортаций.
Если у автора задача построить уровень, вероятно можно строить его полупроцедурно, т.е. комбинировать из десятков готовых частей.
Или строить грид/воксель вычислять свободные места и помечать занятые.

#14
19:12, 23 янв 2023

Virtex
Спасибо, вариант с Physics.CheckBox то, что я искал. Хоть и он иногда пропускает коллизию и интересно, что только на диагонально расположенных объектах. Но в общем, лучше чем все, что я перепробовал.

Как я понимаю:
  - вариант с проверочным BoxCollider не сработал, ибо его я двигал через position.transform и со скоростью 100 блоков в секунду (строчка в 10 блоков спавнилась каждые 0,1 секунд).
  - добавлять массив GameObject[] obstacles и перебирать его при каждом спавне препятствия для трассы на предмет коллизии с другими затратно и трудно. Одновременно препятствий на трассе больше 100. Также имеется метод ресета координат, чтобы избежать Floating Point Errors, что также затрудняет реализацию.
  - добавление OnCollisionEnter или OnTriggerEnter на сами препятствия не сработал, или мне просто ума не хватило.

Страницы: 1 2 Следующая »
ПрограммированиеФорумГрафика