Оптимизация кода на Lua для мобильных игр
Как сделать игру на Lua быстрой и плавной? Разбираем основные приёмы оптимизации кода для мобильных устройств.
Мобильные устройства ограничены по CPU/GPU и памяти. Поэтому скриптовая логика на Lua должна быть предельно лёгкой: минимум аллокаций, меньше работы в каждом кадре, разумная работа со строками и таблицами, бережное отношение к сборщику мусора (GC). Ниже — «скелет» оптимизаций, с которых стоит начать.

1. Профилируем, а не гадаем 🧭
Измеряйте, где теряется время кадра: используйте профайлер вашего движка (Defold, Solar2D/Corona и др.) и внутренние таймеры. Определите горячие функции и оптимизируйте их в первую очередь.
local clock = os.clock
local function bench(fn, iters)
local t0 = clock()
for i=1,iters do fn() end
return (clock()-t0)*1000
end
print("ms:", bench(updateEnemies, 1000))
2. Работа с памятью и GC 🧹
Переиспользуйте таблицы вместо частого создания новых.
Избегайте аллокаций в
update()
и коллизиях.Соберите «пулы объектов» (entity pooling) для снарядов/частиц.
-- Пул на таблицах
local pool = {}
local function acquire()
return table.remove(pool) or {x=0,y=0,vx=0,vy=0,alive=false}
end
local function release(obj)
obj.alive=false; obj.x=0; obj.y=0; obj.vx=0; obj.vy=0
pool[#pool+1]=obj
end
3. Быстрые переменные и модули ⚙️
locals быстрее globals: кэшируйте часто используемые функции.
Сохраняйте ссылки на функции модулей в локальные переменные.
-- Было (медленнее из-за глобальных поисков):
function tick(dt) math.sin(dt); math.cos(dt) end
-- Стало (быстрее благодаря локальным ссылкам):
local sin, cos = math.sin, math.cos
function tick(dt) sin(dt); cos(dt) end
4. Строки и конкатенация 🧵
Строки неизменяемы: каждая конкатенация создаёт новую строку. Накапливайте части в таблице и используйте table.concat
.
-- Плохо:
local s = ""
for i=1,1000 do s = s .. i end
-- Хорошо:
local t = {}
for i=1,1000 do t[i]=i end
local s = table.concat(t, ",")
5. Циклы и итераторы 🔁
Предпочитайте числовой
for
там, где это возможно.ipairs
удобен, но числовойfor i=1,#t
зачастую быстрее.pairs
оставьте для ассоциативных таблиц и не в горячих местах.
-- Быстро:
for i=1,#arr do local v = arr[i]; -- обработка end
6. Метатаблицы и ООП 💼
Методы через метатаблицы удобны, но лишние вызовы и __index
в горячих путях стоят FPS. В критичных местах обращайтесь к полям напрямую или кэшируйте методы в локальные.

ТОП ошибок начинающих разработчиков Lua
Ошибка ❌ | Почему плохо 🐌 | Как исправить ✅ |
---|---|---|
Создание новых таблиц каждый кадр | GC-спайки, микролаги | Пул объектов, очистка и переиспользование |
Конкатенация строк в циклах | Много аллокаций |
|
Глобальные вместо локальных | Доступ медленнее | Кэшируйте в |
| Непредсказуемый порядок/затраты | Числовой |
Тяжёлая логика в | Просадки FPS | Вынесите расчёты, разбейте задачи, кэшируйте |
Подгрузка ассетов «на лету» | Фризы при I/O | Предварительная загрузка, атласы, стриминг аудио |
Пример «до/после»
-- До: много мусора и глобальных обращений
function spawnBullets(n)
for i=1,n do
local b = {x=0,y=0,vx=0,vy=0,alive=true}
table.insert(bullets, b)
end
end
-- После: пулы + локальные ссылки
local insert = table.insert
function spawnBullets(n)
for i=1,n do
local b = acquire() -- из пула
b.alive=true; b.x=0; b.y=0; b.vx=0; b.vy=0
insert(bullets, b)
end
end
Оптимизация Lua на мобильных — это дисциплина: профилируем, исключаем лишние аллокации, кэшируем функции в local
, аккуратно работаем со строками и циклами, используем пулы и атласы. Начните с измерений — и целенаправленно «снимайте» узкие места.
Кодик помогает прокачать навыки оптимизации: мини‑уроки, практические задачи, проверки и подсказки прямо в приложении.
А ещё у нас есть активный telegram-канал, где мы обсуждаем крутые идеи, делимся опытом и вместе разбираем задачи — учиться становится не только полезно, но и весело.