CodeWhiz & Player1
CodeWhiz CodeWhiz
Привет, покопался тут на днях с Unity profiler'ом, нашел несколько классных способов сэкономить миллисекунды в игровом цикле. Хочешь поделимся опытом, как лучше поддерживать стабильные FPS?
Player1 Player1
Звучит круто! Давай, начинаем – я тут уже не первый день вожусь с батчингом, куллингом и GC-пиками. А какой твой самый надежный способ?
CodeWhiz CodeWhiz
За мной всегда в приоритете – следить за циклом обновлений. Тяжелые вычисления перекладываю на Burst-компиляцию, использую статический батчинг для статических мешей, и обязательно пулинг объектов вместо Destroy/Instantiate. Потом включаю профайлер, чтобы выловить скрытые GC-пики, подкручиваю размеры пакетов и настраиваю дальности отсечения, пока фрейм-тайм не станет стабильным. А у тебя как, на что в основном ориентируешься?
Player1 Player1
Круто! Я за то, чтобы рендер-пайплайн был спокойным – обычно добавляю GPU instancing и слежу, чтобы основной поток не грузил себя огромными мешами. Еще я заранее подгружаю текстуры и быстро проверяю скрытые DrawCalls, чтобы GPU не выходил из себя. А у тебя с Burst jobs как? Какие приемы используешь, чтобы они были эффективными?
CodeWhiz CodeWhiz
Отличная организация пайплайна. Для Burst-задач стараюсь держать всё в минимальном объёме: использую NativeArrays с пулом вместо выделения на каждый кадр, применяю IJobParallelForBatch, чтобы компилятор разбивал работу на куски по 64 элемента, и слежу за тем, чтобы все данные находились в непрерывных структурах – чтобы SIMD заработал. Ещё избегаю боксирование и дженерики внутри задачи, делаю функцию статической и использую атрибут BurstCompile с опциями для инлайна небольших вспомогательных функций. Главное – профилировать задачу через Burst-профайлер и убирать лишние копирования памяти, которые не затрагивают GPU. А как ты решаешь задачу потоковой загрузки текстур в цикле?
Player1 Player1
За текстурами я, знаешь, как будто в "беспредел" играю. У меня в очереди висят цепочки текстур с низким разрешением, которые загружаются в фоне, пока основной поток занимается логикой. Использую асинхронную загрузку, чтобы сразу же отправлять данные на GPU, как только они готовы, чтобы кадры не зависали. И ещё одно правило: текстуры не должны задерживаться на стороне CPU дольше, чем один кадр, иначе получишь неприятные просадки. Да и небольшой пул "пустых" текстур держу, чтобы быстро менять их при переходе на новый уровень. А какие у тебя есть хитрости, чтобы текстуры не съедали всю оперативку?