Коротко: на первую рабочую игру хватает шести конструкций Lua: переменная, условие, цикл, функция, обращение к объекту и подписка на событие. Две вещи ломают код из чужих уроков: wait() заменили на task.wait(), а нумерация в таблицах Lua начинается с единицы, а не с нуля.
Lua выбрали для Roblox не случайно: язык маленький. Всё, что в нём есть, умещается на нескольких листах, и ребёнку не нужно изучать половину учебника, прежде чем сделать дверь, которая открывается.
Где вообще живёт скрипт
В Roblox Studio скрипт — это объект, лежащий внутри другого объекта. Положенный в деталь, он управляет именно ею. Положенный в ServerScriptService, работает на весь мир. От места зависит и то, что скрипт видит вокруг себя, и то, когда он запускается.
Типов скриптов три. Обычный Script выполняется на сервере, LocalScript — на компьютере игрока, ModuleScript хранит общий код. Путаница между первыми двумя даёт самые загадочные ошибки первых месяцев: код вроде правильный, но ничего не происходит, потому что серверный скрипт пытается достать интерфейс игрока.
Шпаргалка
| Что нужно | Как пишется |
|---|---|
| Переменная | local zdorovye = 100 |
| Вывести в консоль | print("Привет") |
| Условие | if zdorovye <= 0 then ... end |
| Иначе | elseif ... then и else |
| Цикл со счётчиком | for i = 1, 10 do ... end |
| Бесконечный цикл | while true do ... end |
| Функция | local function otkryt() ... end |
| Объект рядом со скриптом | script.Parent |
| Событие касания | part.Touched:Connect(function(hit) ... end) |
| Пауза | task.wait(1) |
| Комментарий | -- текст после двух дефисов |
Порядок слов в Lua жёсткий: после if обязательно идёт then, после for и while — do. Пропущенное служебное слово Studio замечает сразу, и это та категория ошибок, которая исчезает за первые две недели. Каждый блок закрывается словом end. Именно незакрытый end даёт большинство ошибок в первые недели: Studio подчёркивает строку ниже той, где на самом деле проблема, и ребёнок долго смотрит не туда.
Переменные и то, что в них лежит
Слово local перед именем означает, что переменная живёт только в этом блоке. Без него переменная становится глобальной, и два скрипта начинают незаметно перезаписывать друг другу значения. Привычка писать local всегда экономит часы поиска.
Типов немного: число, строка, логическое значение, таблица и nil — пустота. Последний и даёт самую частую ошибку attempt to index nil value: скрипт обратился к объекту, которого ещё нет или уже нет.
Таблицы: единственная структура данных
В Lua нет отдельно массивов и словарей — есть таблица, работающая и так, и так. Запись local spisok = {"меч", "щит"} создаёт список, spisok[1] достаёт первый элемент.
Именно здесь главная ловушка для тех, кто уже писал на Python или JavaScript: нумерация начинается с единицы. Ребёнок, пришедший из Scratch, этого даже не замечает, а тот, кто знает Python, спотыкается несколько раз подряд.
События: из чего состоит интерактив
Игра в Roblox держится на событиях. Touched срабатывает от касания, MouseButton1Click — от клика по кнопке, PlayerAdded — когда игрок заходит в мир. К каждому подписываются через :Connect(), передавая функцию, которая должна выполниться.
Функция внутри Connect получает аргумент — то, что вызвало событие. В случае Touched это деталь, которая коснулась. Проверка, принадлежит ли она игроку, и есть та строка, которая отличает рабочую ловушку от ловушки, срабатывающей на каждый камень.
Первый скрипт, который мы даём писать, — платформа, исчезающая под ногами. В нём есть всё сразу: событие Touched, пауза, смена свойства и возврат обратно. Шесть строк, зато после них ребёнок понимает устройство любого следующего скрипта.
Свойства: то, что меняют чаще всего
У любого объекта в Studio есть набор свойств, и скрипт меняет их так же, как панель справа. part.Transparency = 0.5 делает деталь полупрозрачной, part.Anchored = true прибивает её на месте, part.BrickColor = BrickColor.new("Bright red") перекрашивает.
Имена свойств пишутся с заглавной буквы и без пробелов — именно здесь дети ошибаются чаще всего, потому что в панели они отображаются иначе. Подсказка простая: что написано в окне Properties без пробелов, то и пишем в коде.
Отдельно стоит запомнить Anchored. Деталь без него падает под действием физики, и половина вопросов «почему моя платформа провалилась» решается одной строкой.
Создать объект кодом
Не всё должно лежать на сцене заранее. Запись local part = Instance.new("Part") создаёт деталь, после чего ей задают свойства и указывают родителя: part.Parent = workspace. Пока родителя нет, объект существует в памяти, но его не видно.
Этот порядок — сначала свойства, потом родитель — не формальность. Если поставить родителя первым, игроки увидят, как деталь мигает и меняет цвет прямо на глазах.
Почему в Studio работает, а в игре нет
Самый неприятный класс ошибок. В режиме Play всё держится на одном компьютере, а на настоящем сервере код разделён: серверный скрипт не видит того, что нарисовал локальный, и наоборот.
Из-за этого кнопка интерфейса должна обрабатываться в LocalScript, а начисление очков — в обычном Script. Связь между ними идёт через RemoteEvent, и это первая по-настоящему взрослая тема курса.
Два изменения, из-за которых чужие уроки не работают
Первое: wait() устарел, и в новых проектах его заменяет task.wait(). Старый вариант пока работает, но Studio подсвечивает его как нежелательный, а видео трёхлетней давности полны именно им. То же случилось со spawn() и delay() — у них теперь есть соответствия в task.
Второе касается способа получить объект. Вместо точечного обращения вроде workspace.Dveri надёжнее писать workspace:WaitForChild("Dveri"): если объект ещё не загрузился, первый вариант вернёт nil, а второй дождётся.
Три ошибки в Output, которые видишь чаще всего
attempt to index nil value означает, что скрипт обратился к объекту, которого нет. Самая частая причина — обращение по имени к детали, которую переименовали или ещё не загрузили. Лечится через WaitForChild и проверкой написания.
attempt to call a nil value — попытка вызвать функцию, которой не существует. Обычно это опечатка в названии или вызов метода через точку вместо двоеточия: part.Destroy() вместо part:Destroy().
Expected 'end' to close 'function' — незакрытый блок. Studio называет строку, где дошла до конца файла, а не ту, где на самом деле забыли слово. Искать надо выше, и быстрее всего помогает аккуратный отступ: правильно сдвинутый код показывает пропущенный end глазами.
Ни одна из этих трёх ошибок не означает, что ребёнок сделал что-то не так. Они случаются у всех, и единственная разница между новичком и опытным — скорость узнавания.
Консоль — главный инструмент
Окно Output в Studio показывает и print, и ошибки с номером строки. Привычка смотреть туда первым делом отличает ребёнка, который продвинется, от того, кто будет звать преподавателя на каждую мелочь.
На курсе Roblox для 9–11 лет большая часть времени уходит именно на чтение ошибок, а не на запоминание слов. В старшей группе 11–14 лет добавляются серверная логика и сохранение данных. Чем путь игрока отличается от пути разработчика, мы разбирали отдельно — в материале Roblox: старт или профессиональная разработка.