Основы Luau в Roblox: синтаксис, таблицы и практические ориентиры
Luau — язык, на котором пишутся скрипты в Roblox. Он похож на Lua, но в Roblox его дополнили инструментами для удобной разработки: подсказки в редакторе, анализ кода и постепенная типизация (когда типы можно добавлять по мере роста проекта).
Если вы открыли Roblox Studio и видите папки вроде Workspace и ServerScriptService, дальше почти всё упирается в три вещи: где лежит ваш скрипт, как он запускается (сервер/клиент) и как вы храните данные.
В этой статье — база Luau: синтаксис, таблицы, функции, режимы проверки типов, работа с ожиданиями через task и типовые ошибки. Для сложных тем оставлены внутренние ссылки, чтобы можно было продолжать чтение цепочкой.
Roblox Studio и инструменты анализа кода развиваются. Если у вас другой интерфейс или предупреждения выглядят иначе, проверьте настройки проекта и версию Studio.
- Что такое Luau и как он связан с Roblox
- С чего начать в Roblox Studio
- Базовый синтаксис Luau без лишней теории
- Таблицы: массивы, словари и самые частые ловушки
- Типы, --!strict и подсказки Studio
- Ожидания, task и параллельное выполнение
- Качество кода: lint и стиль
- Типовые ошибки и чек-лист диагностики
Что такое Luau и как он связан с Roblox
Luau — язык программирования, который встроен в Roblox и используется для логики опыта: движения, интерфейса, предметов, событий, сохранений. Он основан на Lua 5.1, поэтому многие базовые идеи похожи: переменные, функции, таблицы, условия и циклы.
Чем Luau отличается от просто Lua
- Постепенная типизация. Типы можно не писать, но при желании включить проверку и получать подсказки и предупреждения.
- Инструменты Studio. Редактор кода умеет автодополнение, подсказки по API Roblox и анализ скриптов.
- Среда выполнения Roblox. Важнее не сам язык, а то, как он взаимодействует с объектами Roblox (Instance) и сервисами.
Быстрое понимание: что нужно выучить в первую неделю
- Где писать код: Script и LocalScript.
- Как устроены таблицы (Luau table) и почему они встречаются везде.
- Как вызывать функции и передавать параметры.
- Как читать документацию по API: классы, свойства, события.
| Что вы делаете | Обычно это | Где искать дальше |
|---|---|---|
| Логика на сервере | Script в ServerScriptService | Сервер и клиент |
| Локальный интерфейс | LocalScript в StarterPlayerScripts или GUI | GUI |
| Повторно используемый код | ModuleScript и require | Модули |
С чего начать в Roblox Studio
Почти все проблемы новичка в Luau связаны не с синтаксисом, а с окружением: скрипт лежит не там, запускается не в том месте, или редактор не помогает подсказками.
Минимальная настройка перед первой строкой кода
- Откройте окно Explorer и Properties, чтобы видеть, где находится объект и какие у него свойства.
- Создайте скрипт через контекстное меню: вставьте Script или LocalScript в нужную папку.
- Откройте Script Editor и проверьте, что включено автодополнение.
Как понять, что автодополнение работает
- Когда вы начинаете писать имя сервиса или свойства, появляется список вариантов.
- При наведении на функцию или свойство показывается подсказка по API.
Если подсказок нет, сначала проверьте настройку автодополнения в Studio Settings для Script Editor. Если проект большой, подсказки могут появляться с задержкой.
Где учиться на примерах
Для старта удобны короткие уроки по основам программирования и Luau, где объясняют, как читать ошибки, что такое переменные и зачем нужны функции.
Если вы учились по старым видео, вы можете встретить устаревшие рекомендации (например, про wait вместо task.wait). В Roblox чаще ориентируются на текущие страницы документации.
Базовый синтаксис Luau без лишней теории
Luau остаётся динамическим языком: вы можете создать переменную без объявления типа. В большинстве случаев используйте local, чтобы не создавать глобальные переменные случайно.
Переменные и области видимости
- local — переменная видна только внутри блока или файла.
- глобальные — доступны шире, но чаще приводят к конфликтам и трудно отлаживаются.
Условия и циклы
Для ветвления используют if/elseif/else. Для повторений — for и while. В игровых циклах важно не блокировать выполнение: бесконечный while без ожидания быстро создаёт лаги.
Быстрый чек: цикл не должен крутиться без паузы
Если вы пишете while true do, заранее решите, где будет ожидание (например, через task.wait) или переход на событие.
Функции
Функции — такой же тип данных, как число или строка: их можно хранить в таблицах и передавать как параметры. Это удобно для обработчиков событий и коллбеков.
| Что происходит | Вероятная причина | Что сделать |
|---|---|---|
| Переменная вдруг стала nil | Вы переопределили её в другом месте или записали nil в таблицу | Проверьте, где меняется значение, и добавьте проверки на nil |
| Код работает в одном скрипте, но не в другом | Разная среда выполнения (сервер/клиент) или объект недоступен | Проверьте, где лежит скрипт и что он может видеть |
| Ошибка про попытку индексировать nil | Вы обращаетесь к свойству у пустой ссылки | Проверьте путь к объекту и порядок загрузки, используйте ожидание появления объекта |
Таблицы: массивы, словари и самые частые ловушки
Таблица (table) — главный контейнер данных в Luau. В ней хранят и списки, и словари, и структуры вроде объекта. Почти любая сложная логика в Roblox быстро превращается в работу с таблицами.
Два основных режима таблицы
- Массив. Значения лежат по числовым индексам 1, 2, 3 и так далее.
- Словарь. Значения лежат по ключам-строкам или другим значениям.
Частые ошибки с таблицами
| Ситуация | Почему так | Что сделать |
|---|---|---|
| В массиве появился пропуск, и длина стала странной | Элементу присвоили nil, и массив перестал быть непрерывным | Для удаления используйте безопасные приёмы и следите за индексами |
| Данные игрока внезапно общие для всех | Вы используете одну таблицу как шаблон и раздаёте ссылку всем | Создавайте новую таблицу на игрока или делайте копию |
| Порядок обхода словаря разный | Словарь не гарантирует порядок ключей | Если нужен порядок, храните отдельный массив ключей и сортируйте |
Практика: как хранить данные так, чтобы не путаться
- Договоритесь о структуре: какие ключи есть всегда.
- Сделайте одну функцию, которая создаёт новую структуру данных для игрока.
- Не смешивайте в одной таблице и массив, и словарь без явной причины.
Когда таблиц становится много, следующий шаг — модули: вынести работу с данными в ModuleScript.
Типы, --!strict и подсказки Studio
Проверка типов в Luau нужна не для скорости, а для качества: Studio показывает предупреждения ещё до запуска, а автодополнение становится точнее. При этом типы не обязаны быть везде: вы можете добавлять их постепенно.
Режимы проверки типов
| Режим | Что даёт | Когда включать |
|---|---|---|
| nocheck | Практически без анализа типов | Быстрые черновики или старый код, который пока сложно править |
| nonstrict | Мягкие подсказки, меньше ложных срабатываний | Когда хотите подсказки, но не готовы чинить всё сразу |
| strict | Больше предупреждений, требует аккуратности | Модули, библиотеки и критичная логика, где важна предсказуемость |
Как включать режимы на практике
- В начале файла добавьте директиву-комментарий вида --!strict или --!nonstrict.
- Начните с одного-двух модулей, а не со всего проекта.
- Исправляйте предупреждения по смыслу: цель — находить реальные ошибки, а не просто убрать подчёркивания.
Почему подсказки могли поменяться
В Roblox Studio постепенно обновляют систему вывода типов и анализатор. В некоторых проектах это влияет на то, какие предупреждения появляются по умолчанию, и какие настройки доступны на уровне Workspace.
Если после обновления Studio у вас резко выросло число предупреждений, не пытайтесь чинить всё одним коммитом. Сначала зафиксируйте текущую версию, выберите один модуль и настройте режимы проверки по частям.
Минимальный набор типов, который реально помогает
- Типы аргументов и возвращаемых значений у публичных функций модуля.
- Описание структуры таблицы-данных игрока (ключи и типы значений).
- Типы событийных коллбеков: какие параметры приходят в обработчик.
Отдельная статья с примерами аннотаций: типы и аннотации.
Ожидания, task и параллельное выполнение
Игровой код почти всегда работает не линейно: вы ждёте игрока, событие, кадр, ответ сервера. В Luau это делается через уступку управления планировщику (yield) и через библиотеку task.
task: ожидание и планирование
- task.wait — пауза на время или до следующего шага планировщика.
- task.defer и task.spawn — запуск работы без блокировки текущего потока.
Правило для циклов простое: если цикл потенциально бесконечный, в нём должна быть пауза или переход на события. В документации прямо рекомендуют добавлять задержку в бесконечные while-циклы.
Parallel Luau и многопоточность
В Roblox есть модель Parallel Luau: часть работы можно выполнять параллельно на нескольких потоках, чтобы улучшить производительность. Это продвинутая тема, потому что требует понимания, какие операции безопасны в параллельном контексте.
| Задача | Обычно достаточно | Когда думать о параллели |
|---|---|---|
| Обычная игровая логика | События и task.wait при необходимости | Редко |
| Тяжёлые вычисления каждый кадр | Оптимизировать алгоритм и уменьшить частоту | Если всё равно не хватает FPS |
| Массовая обработка данных | Разбить на части и растянуть по кадрам | Если есть явные узкие места |
Отдельная статья по теме: Parallel Luau.
Качество кода: lint и стиль
Когда проект растёт, важно, чтобы код читался и не ломался от мелких правок. В Roblox помогают три вещи: стиль, lint-предупреждения и типы.
Lint: быстрые предупреждения о качестве
Lint-проверки ищут подозрительные места: неиспользуемые переменные, странные выражения, сомнительные конструкции. Это не всегда ошибки, но это хорошие маркеры, где стоит остановиться и перепроверить.
Стиль кода: зачем он нужен
- Единые правила именования и отступов снижают число ошибок при командной работе.
- Понятные имена функций и таблиц помогают быстрее отлаживать.
- Маленькие функции проще тестировать и переносить в модули.
Если вам нужен ориентир по оформлению, удобнее всего взять один стиль-гайд и придерживаться его везде: в скриптах, модулях и именах переменных.
Директивы-комментарии и аккуратность
В Luau есть комментарии, которые начинаются с ! и управляют проверкой типов, линтером и некоторыми оптимизациями. Используйте их осознанно: лучше исправить причину предупреждения, чем полностью отключать проверки.
Отключение lint или type-checking в файле может скрыть реальные ошибки. Если вы отключаете проверки, оставьте себе заметку, почему это сделано и что нужно исправить позже.
Ошибки и диагностика
Если скрипт не работает, начните не с переписывания, а с диагностики. Часто проблема в месте скрипта, в порядке загрузки объектов или в том, что код выполняется не на той стороне (сервер/клиент).
Что проверить сначала
- Открыт ли Output и есть ли там ошибки.
- Где лежит скрипт: ServerScriptService, StarterPlayerScripts, GUI и так далее.
- Не равны ли нужные переменные nil в момент использования.
- Не заблокирован ли поток бесконечным циклом без ожидания.
Таблица: частые ошибки Luau и быстрые решения
| Сообщение или что происходит | Вероятная причина | Что сделать |
|---|---|---|
| attempt to index nil | Объект не найден, путь неверный или ещё не создан | Проверьте путь в Explorer, порядок загрузки, добавьте ожидание появления объекта |
| infinite yield possible | Вы ждёте объект или событие, которое не наступает | Проверьте условие ожидания, добавьте таймаут и логирование |
| Скрипт на клиенте не видит ServerScriptService | Клиент не имеет доступа к серверным контейнерам | Перенесите общий код в ReplicatedStorage и используйте модули или RemoteEvent |
| Предупреждения в strict режиме мешают работе | Недостаточно информации для вывода типов или структура данных не описана | Добавьте аннотации к публичным функциям и ключевым таблицам, либо временно используйте nonstrict |
Где смотреть ошибки после публикации
Для опубликованных опытов есть отчёт по ошибкам, который помогает увидеть проблемы на стороне сервера и клиента без ручного воспроизведения у себя.