Unity3D. Добавление элементов в массив.

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

Unity3D. Добавление элементов в массив.

Сообщение dev01s 03 сен 2018, 16:10

Вечер в хату, теги в радость, селекторы в сладость.
Есть код:
Синтаксис:
Используется csharp
    void Start ()
    {
        for(int i = 0; i < level; i++)
        {
            Spawn();
        }
    }
        void Spawn ()
    {
        GameObject asteroid = asteroids[Random.Range(0, asteroids.Length)];

        float sc1 = Random.Range(minScale, maxScale);
        Vector3 scale = new Vector3(sc1, sc1, sc1);

        GameObject ast = Instantiate(asteroid, PeekLocationOnRadius(Vector2.zero, m_SpawnRadius), Quaternion.identity) as GameObject;
        ast.transform.localScale = scale;
    }

    Vector2 PeekLocationOnRadius (Vector2 origin, float radius)
    {
        var rand = Random.insideUnitCircle.normalized * radius;
        return origin + new Vector2(rand.x, rand.y);
    }

Для краткости: в нем выбирается объект из массива создается с рандомными параметрами и помещается на сцену на определенном радиусе от заданной точки. Все это помещается в цикл и спаунится определенное кол-во раз.
Проблема: объекты могут заспауниться в одинаковой точке.
Вопрос: Как поместить в массив проверку по имеющейся на сцене точке, чтобы не было совпадений?
(Сам профан в си-шарпе, а мой программист еще не родился) Всем спасибо за ответы.
Последний раз редактировалось dev01s 03 сен 2018, 16:34, всего редактировалось 1 раз.
dev01s
UNец
 
Сообщения: 10
Зарегистрирован: 07 июн 2017, 10:15

Re: Unity3D. Добавление элементов в массив.

Сообщение 1max1 03 сен 2018, 16:22

Проблема: объекты могут заспаунится в одинаковой точке.

Очень вряд ли. У Random.insideUnitCircle координаты возвращаются во флоат, а там миллионы комбинаций, так что одинаковые позиции это очень сильно сказано, а вот то что они очень близко находятся друг к другу - это возможно.
Можно сувать в лист все позиции отспавненных объектов и при спавне нового проверять в while цикле не является ли новая позиция очень близкой к старым и менять до тех пор пока не будет далеко (тут нужно понимать что если переборщить с параметрами дальности цикл будет бесконечным), потом когда астероиды улетят (или хз что они у тебя там делают), можно очистить лист.
Последний раз редактировалось 1max1 03 сен 2018, 16:23, всего редактировалось 1 раз.
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: Unity3D. Добавление элементов в массив.

Сообщение getAlex 03 сен 2018, 16:23

Vector3.Distance(a, b) - показывает дистанцию между точками a и b
Если ты знаешь радиус сферы, в которую вписана твоя деталь(не путать со сферой для спавна), то ты можешь проверить через дистанцию, сравнив её с диаметром: есть ли пересечения между новой деталью и остальными деталями в массиве. Если есть пересечение, то создаёшь другую точку.
Но задача не тривиальная т.к. свободного места может не оказаться. А ещё детали могут размещаться не плотно и не качественно, перекрывая много места. Тогда нужно либо сортировать все детали в объёме (гугли алгоритмы упаковки) - что само по себе не простая задача для новичка, либо расширять сферу допустимого спавна детали. Можно ещё схитрить и использовать вытеснение через физику. Тогда произойдёт как бы автоупаковка без всяких алгоритмов, с небольшими рисками получить определённые баги выдавливания фигуры за пределы упаковки. А затем отключаешь физику, после нормализации обьекта в упаковке.
getAlex
Адепт
 
Сообщения: 1775
Зарегистрирован: 10 авг 2013, 18:30

Re: Unity3D. Добавление элементов в массив.

Сообщение dev01s 03 сен 2018, 17:04

1max1 писал(а):
Проблема: объекты могут заспаунится в одинаковой точке.

Очень вряд ли. У Random.insideUnitCircle координаты возвращаются во флоат, а там миллионы комбинаций, так что одинаковые позиции это очень сильно сказано, а вот то что они очень близко находятся друг к другу - это возможно.
Можно сувать в лист все позиции отспавненных объектов и при спавне нового проверять в while цикле не является ли новая позиция очень близкой к старым и менять до тех пор пока не будет далеко (тут нужно понимать что если переборщить с параметрами дальности цикл будет бесконечным), потом когда астероиды улетят (или хз что они у тебя там делают), можно очистить лист.


Извини, не совсем понимаю какой именной лист имеется ввиду. При while мы меняем for или встраиваем его for?
dev01s
UNец
 
Сообщения: 10
Зарегистрирован: 07 июн 2017, 10:15

Re: Unity3D. Добавление элементов в массив.

Сообщение 1max1 03 сен 2018, 17:31

Синтаксис:
Используется csharp
List<Vector2> oldPositions = new List<Vector2>();

    Vector2 PeekLocationOnRadius(Vector2 origin, float radius)
    {
        Vector2 result = Vector2.zero;

        while (true)
        {
            int i = 0;

            result = Random.insideUnitCircle.normalized * radius;

            foreach (var p in oldPositions)
            {
                if (Vector2.Distance(p, result) > 5.0f) // 5 - это мин. дистанция, которая должна быть между всеми объектами
                {
                    ++i;
                }
                else
                    break;
            }

            if (i == oldPositions.Count)
            {
                oldPositions.Add(result);

                return origin + result;
            }
        }
    }


Вот покороче:

Синтаксис:
Используется csharp
List<Vector2> oldPositions = new List<Vector2>();

    Vector2 PeekLocationOnRadius(Vector2 origin, float radius)
    {
        Vector2 result = Vector2.zero;

        while (true)
        {
            result = Random.insideUnitCircle.normalized * radius;

            // Все предыдущие точки находятся на расстоянии больше 5 от result
            if (oldPositions.TrueForAll((v) => Vector2.Distance(v, result) > 5.0f))
            {
                oldPositions.Add(result);

                return origin + result;
            }
        }
    }
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: Unity3D. Добавление элементов в массив.

Сообщение dev01s 03 сен 2018, 17:51

1max1 писал(а):
Синтаксис:
Используется csharp
List<Vector2> oldPositions = new List<Vector2>();

    Vector2 PeekLocationOnRadius(Vector2 origin, float radius)
    {
        Vector2 result = Vector2.zero;

        while (true)
        {
            int i = 0;

            result = Random.insideUnitCircle.normalized * radius;

            foreach (var p in oldPositions)
            {
                if (Vector2.Distance(p, result) > 5.0f) // 5 - это мин. дистанция, которая должна быть между всеми объектами
                {
                    ++i;
                }
                else
                    break;
            }

            if (i == oldPositions.Count)
            {
                oldPositions.Add(result);

                return origin + result;
            }
        }
    }


Вот покороче:

Синтаксис:
Используется csharp
List<Vector2> oldPositions = new List<Vector2>();

    Vector2 PeekLocationOnRadius(Vector2 origin, float radius)
    {
        Vector2 result = Vector2.zero;

        while (true)
        {
            result = Random.insideUnitCircle.normalized * radius;

            // Все предыдущие точки находятся на расстоянии больше 5 от result
            if (oldPositions.TrueForAll((v) => Vector2.Distance(v, result) > 5.0f))
            {
                oldPositions.Add(result);

                return origin + result;
            }
        }
    }


Большое спасибо! Сейчас попробую применить у себя.
dev01s
UNец
 
Сообщения: 10
Зарегистрирован: 07 июн 2017, 10:15

Re: Unity3D. Добавление элементов в массив.

Сообщение seaman 03 сен 2018, 20:09

Учтите, что может быть бесконечный цикл.
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара


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

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

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