Войти
UnityФорумПрограммирование

Оптимизация списка объектов Unity

#0
14:56, 24 янв 2023

Задача состоит в том, чтобы создавать одинаковые объекты и ставить их в строчку, удаляя каждый через t секунд. В итоге имеем дорожку определенного размера, которая движется в направлении спавна следующего объекта.

Чтобы не создавать и потом удалять каждый отдельный объект, реализован паттерн Список объектов. Если есть свободные объекты (activeInHierarchy(false)), то ищу его в List<List<GameObject>> usedObjects[типОбъекта][номер], присваиваю activeInHierarchy(true), устанавливаю на нужную позицию.
Если свободных нету, то создаю такой (Instantiate(gameObject)), присваиваю activeInHierarchy(true), добавляю в лист usedObjects.
Одновременно объектов около 3000.

В профайлере я заметил, что Object.Instantiate занимает в разы меньше времени чем поиск по листу и проверка каждого значения на activeInHierarchy.


Получается, паттерн Список объектов не имеет смысла?
Или я не туда смотрю?
Или это мои кривые куки?

Screenshot | Оптимизация списка объектов Unity
private GameObject GetObject(int objName)
    {
        GameObject obj = null;

        if (usedObjects[objName].Count > 0)
            for (int i = 0; i < usedObjects[objName].Count; i++)
                if (!usedObjects[objName][i].activeInHierarchy)
                    obj = usedObjects[objName][i];
        
        if (notEnoughtObjectsInPool)
        {
            obj = Instantiate(objectPool[objName].obj);
            obj.SetActive(false);
            usedObjects[objName].Add(obj);
        }

        return obj;
    }
#1
15:26, 24 янв 2023

Закэшируй сведения о видимости объектов. Проверка списка bool будет всяко быстрее, чем get_activeInHierarchy

#2
15:44, 24 янв 2023

Бегать циклом по 3к объектам это конечно будет медленнее, чем Instantiate.

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

Instantiate плох тем, что игра лезет в память. GarbageCollector вроде бы уже давно оптимизирован, фризов из-за очистки памяти таких, как 5-7 лет назад, быть не должно. Если уж и избегать создания объектов, то простыми и лёгкими пулами, а не огромной системой на все случаи жизни

#3
20:04, 24 янв 2023

LifeKILLED
> фризов из-за очистки памяти таких, как 5-7 лет назад, быть не должно
подтверждаю

#4
(Правка: 22:38) 22:37, 24 янв 2023

Убрал лист, теперь просто создаю нужный объект и удаляю его.
Кто скажет, почему после 8000 вызовов (за 80 сек) Instantiate прекращает работать, а Physics.CheckBox возвращает только true?

#5
23:07, 24 янв 2023

Задача состоит в том, чтобы создавать одинаковые объекты и ставить их в строчку, удаляя каждый через t секунд

Вы каждый раз генерируете новые объекты заново. Вам лучше перед началом игры сгенерировать, необходимое количество объектов, а как оно пропадаю из поля зрения переносить их в новое место.
Какой смысл создавать объект, потом удалять, что бы его потом опять создать?
Можно сделать его gameObject.SetActive(false) и он перестанет быть видимым.

#6
(Правка: 23:37) 23:32, 24 янв 2023

FourGen
А Вы мое первое сообщение перечитайте, и поймете (я изначально так и делал).

Чтобы не создавать и потом удалять каждый отдельный объект, реализован паттерн Список объектов.
Одновременно объектов около 3000.
Object.Instantiate занимает в разы меньше времени чем поиск по листу и проверка каждого значения на activeInHierarchy.

#7
23:59, 24 янв 2023

>Qwerty
Ээээ странно. Ну ладно.

#8
0:15, 25 янв 2023

Qwerqe
> Убрал лист, теперь просто создаю нужный объект и удаляю его
а чем решение из #2 не подходит?
Free List это может быть что угодно, главное что текущий свободный элемент всегда лежит в Head
доступ всегда за O(1)
вместо безумных тыщ

#9
17:58, 25 янв 2023

Тоже не понимаю, зачем проходить весь список, если первый объект это 0, а последний это count.

#10
18:43, 25 янв 2023

sledo
count - 1

#11
(Правка: 9:55) 9:47, 26 янв 2023

CircularBuffer ?
usedObjects[objName]  достань в переменную, глаза болят и профайлер страдает
хранить не обьекты а (GameObject item,bool active)
activeInHierarchy - всегда перебор

#12
18:32, 27 янв 2023

Я так понимаю, речб про Object Pool?
Храни список (лучше stack) свободных объектов. Когда выдаёшь его в пользование - убираешь из списка. Когда попользованный объект тебе возвращают - добавляешь в список. Чтобы пользователь объекта не задумывался про пул, добавляешь на все объекты компоненту типа PooledObject, которая хранит ссылку на свой родной пул и имеет OnDisable(), который возвращает объект в пул.

Не используй activeInHierarchy, эта штука проверят всех родителей объекта по цепочке, а как у неё работает сеттер, я даже поюсь представить) Используй activeSelf - это по сути галочка на самом геймобджекте в инспектора, 1-в-1

Убери из реализации пула фигню с [типОбъекта], пул должен быть однородным. Если тебе нужны пулы разных объектов - заведи несколько отдельных пулов. (Это чисто про быдлокод и кривые руки)

#13
19:19, 27 янв 2023

meekobold
> Убери из реализации пула фигню с [типОбъекта]
генерики жи

UnityФорумПрограммирование