Большие открытые локации в Roblox часто вызывают сильные просадки кадров на смартфонах из-за перегрузки видеочипа вызовами отрисовки (Draw Calls) и миллионами полигонов.
Используя `RenderFidelity.Performance`, процедурные скрипты дистанционного переключения в Luau и 2D-импосторы для дальних планов, можно обеспечить стабильные 60 кадров в секунду на любых устройствах.
1. Узкое место мобильных GPU: вызовы отрисовки и полигоны
Анализ ограничений движка Roblox на смартфонах:
- Перегрузка Draw Calls: более 1500 вызовов отрисовки за кадр перегружают мобильный процессор.
- Бесполезные вершины: рендеринг далеких деревьев из тысяч полигонов тратит ресурсы видеочипа впустую.
- Частая смена текстур: отсутствие атласов текстур тормозит графический конвейер.
- Троттлинг от нагрева: при высокой нагрузке телефон сбрасывает частоты, роняя FPS с 60 до 20.
2. RenderFidelity и встроенная система LOD в Roblox
Эффективное применение автоматического упрощения мешей:
- `RenderFidelity.Precise`: оставляет 100% геометрии; использовать только для предметов в руках игрока.
- `RenderFidelity.Performance`: автоматически создает 4 уровня упрощения (100%, 50%, 25%, 12.5%).
- `CollisionFidelity.Box`: упрощение хитбоксов декораций для разгрузки физического движка.
- Автоматический инстансинг: одинаковые меши с одинаковыми материалами отрисовываются за один вызов.
--!strict
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
local LODManager = {}
type LODModel = { HighDetail: Model, LowDetail: Model, Impostor: BillboardGui, Position: Vector3, CurrentTier: number }
local registeredLODs: {LODModel} = {}
function LODManager.Register(high: Model, low: Model, impostor: BillboardGui, centerPos: Vector3)
table.insert(registeredLODs, { HighDetail = high, LowDetail = low, Impostor = impostor, Position = centerPos, CurrentTier = 1 })
low.Parent = nil
impostor.Enabled = false
end
local frameCounter = 0
RunService.Heartbeat:Connect(function()
frameCounter += 1
if frameCounter % 6 ~= 0 then return end
local camera = Workspace.CurrentCamera
if not camera then return end
local camPos = camera.CFrame.Position
for _, lod in ipairs(registeredLODs) do
local offset = lod.Position - camPos
local distSq = offset.X * offset.X + offset.Y * offset.Y + offset.Z * offset.Z
local newTier = distSq > 640000 and 4 or (distSq > 122500 and 3 or (distSq > 14400 and 2 or 1))
if newTier ~= lod.CurrentTier then
lod.CurrentTier = newTier
lod.HighDetail.Parent = (newTier == 1) and Workspace or nil
lod.LowDetail.Parent = (newTier == 2) and Workspace or nil
lod.Impostor.Enabled = (newTier == 3)
end
end
end)
return LODManager
3. 2D-импосторы и замена далекой геометрии
Переход от тяжелых 3D-моделей к плоским спрайтам:
- Суть импосторов: дальше 300 студов здания и деревья заменяются плоской текстурой без заметной потери качества.
- Колоссальное сокращение вершин: миллионы полигонов дальнего леса сжимаются до нескольких сотен.
- Общий атлас: спрайты на одном листе снижают число вызовов отрисовки до минимума.
- Дизеринг: плавное растворение исключает резкое скачкообразное появление объектов.
4. StreamingEnabled и экономия оперативной памяти
Динамическая загрузка тяжелых миров:
- Ограниченный StreamingMinRadius для предотвращения вылетов при спавне.
- `ModelStreamingMode.Atomic`: загружает транспорт и лифты строго целиком.
- `ModelStreamingMode.Persistent`: оставляет главные достопримечательности всегда в памяти.
- Реакция на нехватку памяти: автоматическое снижение дальности видимости при предупреждениях системы.
5. Чек-лист оптимизации под мобильные платформы
Обязательные правила для плавной игры:
- Объединение текстур мелких предметов в атласы 1024x1024.
- Отключение CastShadow у мелких декораций (трава, камни).
- Контроль в MicroProfiler: время кадра должно быть строго ниже 16.6 мс.
- Регулярное тестирование на слабых смартфонах.
Frequently Asked Questions
Чем скриптовый LOD лучше встроенного RenderFidelity?
RenderFidelity лишь уменьшает полигоны, а скрипт может заменить тяжелую модель на 2D-картинку или выключить ее совсем.
Помогает ли отключение коллизий графике?
Да, так как это снижает нагрузку на пространственные структуры движка перед отрисовкой кадра.
Сколько Draw Calls безопасно для мобильных устройств?
От 400 до 800 вызовов. При превышении 1200 возможны перегрев и потеря кадров.