Туториал · Основы скриптинга

Как писать скрипты в Roblox Studio: гайд для начинающих

Скриптинг, или программирование, в Roblox Studio означает писать на Luau, версии языка Lua от Roblox, в скриптах, которые вы добавляете в плейс. Этот гайд начинается с пустого Baseplate: вы откроете окно Output, напишете первый скрипт, измените парт из кода, отреагируете на игрока, наступившего на площадку, и попробуете LocalScript, а по пути разберётесь с переменными, функциями, условиями, циклами и событиями.

Обновлено 26 октября 2026 г.18 мин чтения

Коротко

Чтобы написать скрипт в Roblox Studio, наведите курсор на ServerScriptService в Explorer, нажмите + и вставьте Script. Studio откроет его в Script Editor. Напишите Luau, например print("Hello"), нажмите Play (F5) и прочитайте результат в окне Output (меню Window или вкладка Script). Script выполняется на сервере и меняет всё для всех; LocalScript в StarterPlayerScripts выполняется на устройстве одного игрока.

  • Сначала выучите четыре идеи: переменные (local coins = 3), функции (local function name() ... end), условия if и события (part.Touched:Connect(...)). Четыре скрипта этого гайда построены из них, плюс циклы и таблицы.
  • Используйте task.wait(), а не wait(). Справочник Roblox помечает глобальный wait() устаревшим и заменённым на task.wait().
  • В настройках отображения окна Output включите Show Context, чтобы каждая строка показывала, пришла она с Server или с Client.
На этой странице
  1. Перед началом
  2. 1. Первый скрипт
  3. 2. Изменить парт
  4. 3. События
  5. 4. Первый LocalScript
  6. 5. Тест
  7. Куда класть скрипты
  8. Чтение ошибок
  9. Старые туториалы
  10. Практика
  11. Что дальше
  12. Common errors
  13. С RoCode
  14. Частые вопросы
  15. Источники и что почитать

Перед началом: Studio, Baseplate и окно Output

ИллюстрацияЧетыре скрипта в одном плейтесте: парт ColourChanger меняет цвет каждую секунду, шаг на Pad делает его жёлтым на 2 секунды для всех игроков и пишет ваше имя в Output, а E делает Pad прозрачнее только на этом экране.

Нужны Roblox Studio и аккаунт Roblox, и больше ничего: ни редактора кода, ни плагина. Каждый скрипт этого гайда набирается в собственном Script Editor Studio.

  1. Установите Roblox Studio, бесплатное приложение Roblox для Windows и Mac, и войдите через аккаунт Roblox.
  2. Откройте Studio. На стартовой странице есть шаблоны: выберите Baseplate. Вы получите пол с текстурой сетки 4x4 и SpawnLocation, место, где появляется ваш аватар при игре.
  3. Если окна Explorer и Properties не видны, откройте их из меню Window или вкладки Home. Explorer перечисляет все объекты плейса; Properties показывает настройки выделенного.
  4. Откройте Output из меню Window или вкладки Script. Здесь появляются сообщения и ошибки ваших скриптов.
  5. В настройках отображения окна Output включите Show Context, который помечает каждое сообщение как Client или Server, и Show Source, который показывает скрипт и номер строки, откуда оно пришло.
Четыре скрипта, которые вы напишете
СкриптТипГде лежитЧему учит
FirstScriptScriptServerScriptServiceПеременные, функция, условие if, циклы и таблица
ColourChangerScriptВнутри Part в WorkspaceИзменение свойств, script.Parent и цикл с ожиданием
TouchPadScriptВнутри Part с именем PadСобытия, поиск игрока, коснувшегося парта, и debounce
MyFirstLocalScriptLocalScriptStarterPlayerScripts, внутри StarterPlayerКод на устройстве одного игрока, нажатия клавиш и что остаётся на этом устройстве
Explorer в конце (только объекты этого гайда)
Workspace
  Baseplate Part
  SpawnLocation SpawnLocation
  Part Part new
    ColourChanger Script new
  Pad Part new
    TouchPad Script new
ServerScriptService
  FirstScript Script new
StarterPlayer
  StarterPlayerScripts
    MyFirstLocalScript LocalScript new

Шаг 1: напишите первый скрипт

  1. В Explorer наведите курсор на ServerScriptService, нажмите + и выберите Script (сочетание Ctrl+I или ⌘I на Mac). Studio создаст скрипт и откроет его в Script Editor.
  2. Нажмите на новый скрипт правой кнопкой, выберите Rename и назовите его FirstScript. Имя не меняет того, что делает скрипт, но говорит, какой скрипт что напечатал.
  3. Новые скрипты начинаются с одной строки, print("Hello world!"). Удалите её и вставьте код ниже.
  4. Нажмите Play (F5), выбрав Test в списке слева от неё. Studio запустит плейтест и поставит аватар на SpawnLocation.
  5. Прочитайте строки в Output, затем нажмите Stop (Shift+F5). Stop также возвращает все объекты в состояние до нажатия Play, поэтому всё, что вы сдвинули или перекрасили во время игры, вернётся.
Script в ServerScriptService с именем FirstScript
-- Script в ServerScriptService с именем FirstScript.
-- Ваш первый Luau: переменные, функция, условие if, цикл и таблица.
-- Нажмите Play (F5) и прочитайте результат в окне Output.

-- Переменная это имя, которое хранит значение
local gameName = "Coin Run"
local coinsToWin = 3

-- Функция это именованный блок кода, который можно запускать сколько угодно раз.
-- name и goal это её параметры; return возвращает значение тому, кто её вызвал.
local function describe(name: string, goal: number): string
	return `{name}: collect {goal} coins to win`
end

print(describe(gameName, coinsToWin)) --> Coin Run: collect 3 coins to win

-- Условие if выполняет код, только когда условие истинно
if coinsToWin > 5 then
	print("That is a long game")
elseif coinsToWin > 1 then
	print("That is a short game")
else
	print("One coin and you win")
end

-- Цикл for повторяет код заданное число раз
for count = 1, coinsToWin do
	print("Coin number", count)
end

-- Таблица хранит список значений; этот цикл обходит их по порядку
local colours = { "Red", "Green", "Blue" }
for position, colour in colours do
	print(position, colour) --> 1 Red, затем 2 Green, затем 3 Blue
end

Всё после -- в строке это комментарий: Luau его пропускает, поэтому можно оставлять себе заметки. Комментарии --> показывают, что печатает строка.

Output должен показать эти восемь строк вперемешку с сообщениями самого Studio. Когда print получает несколько значений, он ставит между ними пробел. С включёнными Show Context и Show Source каждая строка ещё помечена Server и FirstScript с номером строки.

Output (ожидаемый)
Coin Run: collect 3 coins to win
That is a short game
Coin number 1
Coin number 2
Coin number 3
1 Red
2 Green
3 Blue

Сопоставьте каждую строку с кодом, который её напечатал. Позже вы будете делать то же с сообщениями об ошибках, так что привычка пригодится.

FirstScript использует только чистый Luau без объектов Roblox, поэтому он работает и в бесплатной песочнице Luau в браузере. Поменяйте там значение и запустите снова, чтобы увидеть, что изменится.

Что делает каждая часть FirstScript
КодИдеяЧто это значит
local gameName = "Coin Run"ПеременнаяИмя, которое хранит значение. local значит, что пользоваться им может только этот скрипт или блок, в котором оно стоит. Текст в кавычках это строка; 3 это число. Имена чувствительны к регистру, поэтому coinsToWin и CoinsToWin это две разные переменные.
local function describe(name: string, goal: number): stringФункцияИменованный блок кода, который можно запускать сколько угодно раз. name и goal это её параметры: значения, которые передаются при каждом вызове. : string и : number это необязательные аннотации типов. Luau использует их, чтобы предупреждать об ошибках в Script Editor; без них код работает так же.
returnВозвращаемое значениеОтдаёт значение коду, который вызвал функцию. print(describe(gameName, coinsToWin)) печатает то, что вернёт describe.
`{name}: collect {goal} coins to win`Интерполяция строкТекст в обратных кавычках может содержать значения: Luau заменяет {name} и {goal} их текущими значениями.
if, elseif, else, endУсловие ifLuau проверяет условия сверху вниз и выполняет только первое истинное. coinsToWin равно 3, это не больше 5, но больше 1, поэтому печатается только «That is a short game».
for count = 1, coinsToWin doЧисловой цикл forВыполняет код внутри по разу для каждого числа от 1 до coinsToWin, где count равен 1, потом 2, потом 3.
{ "Red", "Green", "Blue" } и for position, colour in colours doТаблица и циклТаблица как список, Luau называет это массивом. Позиции начинаются с 1, а не с 0. Цикл обходит каждый элемент и даёт его позицию и значение.

Каждый блок, который открывается словом function, if, for или while, закрывается словом end. Один пропущенный end не даёт запуститься всему скрипту; раздел чтение ошибок показывает, какое сообщение вы получите.

Шаг 2: измените парт из скрипта

Скрипты становятся полезными, когда меняют что-то в мире. Настройки, которые вы видите в окне Properties, например Color, Transparency или Anchored у парта, это свойства, и скрипт тоже может их задавать.

  1. На вкладке Home нажмите Part. Studio добавит блок в Workspace. Его имя неважно.
  2. В Explorer наведите курсор на новый парт, нажмите + и вставьте Script. Переименуйте его в ColourChanger и замените содержимое кодом ниже.
  3. Нажмите Play. Парт становится красным, затем синим, затем зелёным, меняясь раз в секунду, и начинает снова.
Script в любом парте в Workspace с именем ColourChanger
-- Script внутри Part в Workspace, с именем ColourChanger.
-- Скрипты меняют те же свойства, что видны в окне Properties.
-- Этот даёт своему парту новый цвет каждую секунду, для всех игроков.

local part = script.Parent :: BasePart -- парт, внутри которого лежит этот скрипт

local colours = {
	Color3.fromRGB(255, 85, 85), -- красный
	Color3.fromRGB(85, 170, 255), -- синий
	Color3.fromRGB(85, 255, 127), -- зелёный
}

part.Anchored = true -- закреплённый парт остаётся там, где вы его поставили

local index = 1
while true do
	part.Color = colours[index]
	index = index % #colours + 1 -- 1, 2, 3, затем снова 1
	task.wait(1) -- пауза на одну секунду (старый wait() устарел)
end
  • script.Parent это объект, внутри которого лежит скрипт, здесь парт. Перетащите скрипт в другой парт, и он будет менять тот.
  • :: BasePart это приведение типа. Оно говорит Script Editor, что родитель это парт, чтобы проверять используемые свойства. Luau использует типы только для предупреждений и подсказок, поэтому приведение не меняет того, что делает строка.
  • part.Color и part.Anchored это те же свойства, что в окне Properties, с теми же именами. Roblox использует американское написание, поэтому свойство называется Color, хотя скрипт называется ColourChanger.
  • Anchored = true держит парт на месте: справочник Roblox говорит, что закреплённый парт никогда не двигается из-за гравитации, столкновений или другой физики.
  • colours[index] читает один элемент списка. #colours это длина списка, 3, а % даёт остаток от деления, поэтому index % #colours + 1 считает 1, 2, 3, 1, 2, 3.
  • while true do повторяется бесконечно, поэтому task.wait(1) внутри так важен. Документация Roblox говорит всегда ставить задержку вроде task.wait() в бесконечный цикл: без неё игра зависает, а Studio падает.

ColourChanger это Script, поэтому он работает на сервере, и все игроки видят один и тот же цвет одновременно. Шаг 4 показывает другой вид скрипта.

Шаг 3: реагируйте на игрока через событие

Большая часть игрового кода ждёт, пока что-то случится: игрок зашёл, парта коснулись, кнопку нажали. Roblox называет это событиями. Чтобы выполнить код, когда событие срабатывает, к нему подключают функцию.

  1. Вставьте ещё один Part и переименуйте его точно в Pad, с заглавной P. Оставьте его прямо в Workspace, не в папке и не в модели, потому что LocalScript на шаге 4 ищет его там.
  2. Сделайте его плоской площадкой, на которую можно встать, например задайте Size равным 6, 1, 6 в окне Properties. Поставьте его на пол рядом со SpawnLocation и отметьте Anchored, чтобы он не двигался.
  3. Наведите курсор на Pad, нажмите +, вставьте Script, переименуйте его в TouchPad и вставьте код ниже.
  4. Нажмите Play и встаньте на площадку. Она желтеет на 2 секунды, а Output называет ваше имя.
Script в Workspace.Pad с именем TouchPad
-- Script внутри Part в Workspace с именем Pad, скрипт с именем TouchPad.
-- События: когда игрок наступает на площадку, она светится жёлтым, а Output пишет, кто это был.
-- Debounce не даёт коду срабатывать много раз в секунду, пока игрок стоит на ней.

local Players = game:GetService("Players")

local pad = script.Parent :: BasePart
local COOLDOWN_SECONDS = 2

local normalColour = pad.Color
local busy = false

local function onTouched(otherPart: BasePart)
	if busy then
		return -- ещё идёт перезарядка после прошлого касания
	end
	-- Персонаж это Model, в которой лежит часть тела (или шляпа), коснувшаяся площадки
	local character = otherPart:FindFirstAncestorOfClass("Model")
	local player = character and Players:GetPlayerFromCharacter(character)
	if not player then
		return -- коснулся свободный парт или NPC, а не игрок
	end

	busy = true
	print(`{player.Name} stepped on the pad`)
	pad.Color = Color3.fromRGB(255, 220, 0)
	task.wait(COOLDOWN_SECONDS)
	pad.Color = normalColour
	busy = false
end

pad.Touched:Connect(onTouched)
Как TouchPad доходит от касания до игрока
КодЧто делает
pad.Touched:Connect(onTouched)Подключает функцию к событию Touched площадки, поэтому Roblox запускает onTouched каждый раз, когда что-то касается площадки, и передаёт коснувшийся парт.
otherPartПарт, который коснулся площадки: стопа, нога, ручка шляпы или инструмент в руке игрока. Это никогда не сам игрок, поэтому следующие две строки выясняют, кому он принадлежит.
otherPart:FindFirstAncestorOfClass("Model")Поднимается от этого парта к первому предку, чей класс ровно Model, то есть к персонажу. Поскольку имя класса должно совпадать точно, он пропускает шляпу (класс Accessory) и инструмент в руке (класс Tool).
Players:GetPlayerFromCharacter(character)Возвращает Player, чей это персонаж, или nil, если это ничей персонаж, например NPC. character and впереди пропускает вызов, если модель не найдена, и player остаётся nil.
if not player then return endОстанавливается здесь для всего, что не игрок. return выходит из функции досрочно.

Зачем площадке debounce

Страница Roblox о debounce предупреждает, что Touched срабатывает несколько раз подряд, пока парты соприкасаются, а у идущего персонажа несколько частей тела. Без проверки один шаг на площадку мог бы напечатать много строк и снова и снова перезапускать жёлтое свечение.

Переменная busy и есть debounce. Первое касание ставит её в true, и каждое касание в следующие 2 секунды доходит до if busy then return end и останавливается. После task.wait(COOLDOWN_SECONDS) площадка возвращает цвет, а busy снова становится false. COOLDOWN_SECONDS написан заглавными, потому что это настройка, которая не меняется во время игры: так Roblox советует называть константы.

У этой площадки один debounce на всех, поэтому второй игрок, наступивший в эти 2 секунды, игнорируется. Для светящейся площадки это нормально. Площадка, которая выдаёт награды, должна держать перезарядку для каждого игрока, как площадка с монетами в гайде по таблице лидеров.

Шаг 4: первый LocalScript и чем он отличается

Работающая игра это один сервер плюс по клиенту на каждого игрока. Всё до сих пор было Script, который работает на сервере, поэтому его изменения доходят до всех игроков. LocalScript работает на устройстве одного игрока. Нажатия клавиш, камера и экранные меню обрабатываются там, потому что о них знает только это устройство.

  1. В Explorer раскройте StarterPlayer, наведите курсор на StarterPlayerScripts, нажмите + и вставьте LocalScript. Переименуйте его в MyFirstLocalScript и вставьте код ниже.
  2. Нажмите Play. Output покажет Hello, и ваше имя с пометкой Client.
  3. Щёлкните по окну игры и нажмите E. Площадка становится прозрачнее. Нажмите E снова, чтобы вернуть её.
  4. Пока плейтест идёт, нажмите переключатель Client/Server в элементах тестирования Studio, чтобы перейти к серверной копии игры. Там площадка непрозрачна: сервер ничего не узнал об изменении.
LocalScript в StarterPlayerScripts с именем MyFirstLocalScript
-- LocalScript в StarterPlayer > StarterPlayerScripts с именем MyFirstLocalScript.
-- LocalScript работает на устройстве одного игрока. Нажмите E: Pad становится прозрачнее только
-- на вашем экране, потому что изменение парта отсюда не доходит ни до сервера, ни до других.

local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")

local player = Players.LocalPlayer
print(`Hello, {player.Name}`) -- появляется в Output с пометкой Client

UserInputService.InputBegan:Connect(function(input: InputObject, gameProcessed: boolean)
	if gameProcessed then
		return -- клавиша ушла на другое, например на набор текста в чате
	end
	if input.KeyCode == Enum.KeyCode.E then
		local pad = workspace:FindFirstChild("Pad")
		if pad and pad:IsA("BasePart") then
			pad.Transparency = if pad.Transparency == 0 then 0.6 else 0
		end
	end
end)
  • Players.LocalPlayer это игрок, на чьём устройстве работает скрипт. Roblox определяет его только для LocalScript и ModuleScript, которые они подключают, поэтому серверный код его использовать не может.
  • UserInputService.InputBegan срабатывает, когда игрок начинает нажатие клавиши, клик или касание. gameProcessed равен true, когда движок уже использовал этот ввод, например клик по кнопке или клавишу в строке чата, поэтому скрипт его игнорирует.
  • workspace:FindFirstChild("Pad") возвращает потомка с именем Pad или nil, если его нет. pad:IsA("BasePart") проверяет, что это действительно парт, прежде чем скрипт поменяет его Transparency.
  • if pad.Transparency == 0 then 0.6 else 0 это if-выражение: оно выбирает одно из двух значений. Transparency 0 значит полностью видимый, 1 невидимый.
  • Скрипт спринта на Shift хорош как второй LocalScript: он слушает клавишу и меняет WalkSpeed персонажа.
Script, LocalScript и ModuleScript
ТипГде работаетКуда доходят измененияДля чегоОбычно лежит в
ScriptНа сервереДо всех игроковПравила игры: монеты, урон, двери, раунды, сохранениеServerScriptService или внутри парта, пока учитесь
LocalScriptНа устройстве одного игрокаТолько на это устройство, кроме движения своего персонажаВвод, камера, экранные меню, эффекты для одного игрокаStarterPlayerScripts или StarterGui
ModuleScriptНа той стороне, которая вызывает для него require()Туда же, куда и у подключившего скриптаКод, общий для нескольких скриптовReplicatedStorage для обеих сторон, ServerScriptService только для сервера

Что может изменить читер

Считайте, что читер контролирует всё на своём устройстве. Он может запускать свои LocalScript и менять ваши, поэтому может сделать прозрачной площадку или что угодно ещё на своём экране. Здесь это безвредно: прозрачность только для вида и остаётся на его устройстве. Именно поэтому всё важное решает Script на сервере.

Серверный Script тоже не безопасен автоматически. TouchPad работает на сервере, но устройство каждого игрока управляет физикой его персонажа, и документация Roblox по безопасности называет среди того, что клиент может делать с подконтрольными партами, управление моментом срабатывания Touched или полную его блокировку. Для светящейся площадки это неважно. Для площадки, которая платит, проверяйте ещё и то, что сервер отслеживает сам, как правило в гайде по обби, что чекпоинты засчитываются только по порядку.

Шаг 5: протестируйте все четыре скрипта вместе

  1. Очистите Output через Ctrl+K (⌘K на Mac) и нажмите Play (F5). Output покажет восемь строк FirstScript с пометкой Server и вашу строку Hello с пометкой Client. Парт ColourChanger меняет цвет каждую секунду.
  2. Встаньте на площадку. Она желтеет на 2 секунды, а Output один раз показывает ваше имя и «stepped on the pad». Походите по ней: новая строка появляется не чаще раза в 2 секунды, а не при каждом срабатывании Touched.
  3. Нажмите E. Площадка становится полупрозрачной (Transparency 0.6). Нажмите E снова, и она непрозрачна.
  4. Нажмите Stop. В списке тестирования выберите Server & Clients, поставьте 2 клиента и нажмите Play (или F7). Studio откроет окно сервера и два окна клиентов. В одном клиенте нажмите E: площадка станет прозрачнее там, а другой клиент и сервер покажут её непрозрачной. Нажмите End Session, когда закончите.
  5. Сломайте что-нибудь нарочно. Переименуйте Pad в Pad2 и запустите игру. Шаг на площадку всё ещё делает её жёлтой, потому что TouchPad находит свой парт через script.Parent, а не по имени. Нажатие E теперь ничего не делает, и ошибки нет: FindFirstChild("Pad") вернул nil, а проверка if pad and ... тихо пропустила остальное. Добавьте print(pad) на строку после FindFirstChild, запустите и нажмите E: Output покажет nil. Такой print самый быстрый способ понять, почему скрипт ничего не делает. Остановите игру, удалите строку с print и верните парту имя Pad.

Куда класть скрипты

От того, где лежит скрипт, зависит, запустится ли он вообще, и Studio не предупреждает, если он не запустится никогда. Для следующих ваших скриптов:

Куда класть каждый вид скрипта
КонтейнерЧто кластьПочему
ServerScriptServiceСкрипты с большинством правил игры: награды, раунды, сохранениеОни работают на сервере, и ничего из ServerScriptService не отправляется игрокам.
Внутри парта в WorkspaceScript, который относится к одному парту, как ColourChanger и TouchPadНормально, пока учитесь: парт это script.Parent. Для настоящих проектов Roblox советует вместо этого помечать парты тегами (см. ниже).
StarterPlayerScripts, внутри StarterPlayerБольшинство LocalScript: ввод, камера, эффекты для одного игрокаКаждый игрок получает свою копию при входе.
StarterGuiLocalScript внутри ScreenGui, которые управляют экранным менюКаждый игрок получает свою копию интерфейса.
ReplicatedStorageModuleScript, которые подключает и серверный, и клиентский кодЕго видят обе стороны. LocalScript или Script с настройками по умолчанию здесь никогда не запустится.

Страница Roblox о расположении скриптов советует вообще не класть скрипты прямо в парты в Workspace: пометьте парты тегами и работайте с ними из одного ModuleScript через CollectionService. Скрипт внутри парта всё равно самый простой старт, и для одного-двух объектов, пока вы учитесь, это нормально. Гайд по дверям показывает шаблон с тегами, с одним скриптом на все двери, а гайд о клиенте и сервере содержит полную таблицу, какие контейнеры какие скрипты запускают.

Когда что-то пошло не так: читайте Output

Ошибки показываются в Output красным. Каждая начинается с того, где она произошла, полного имени скрипта и номера строки, а потом говорит, что не так. Нажмите на ошибку, и Studio откроет скрипт на этой строке. Например, если вы удалите проверку if not player из TouchPad, а на площадку упадёт свободный парт, Output покажет:

Output (пример)
Workspace.Pad.TouchPad:22: attempt to index nil with 'Name'

Ошибки в том, как написан код, например пропущенный end, видны ещё до нажатия Play: Script Editor подчёркивает их красным, а окно Script Analysis (кнопка Analysis на вкладке Script) их перечисляет. Скрипт с такой ошибкой не запускается вообще, даже строки выше неё.

Три ошибки, которые стоит узнавать
СообщениеЧто значитКак исправить
Colour is not a valid member of Part "Workspace.Part"У этого объекта нет ничего с таким точным именем. Здесь свойство пишется Color.Сверьте написание и заглавные буквы с окном Properties или Explorer. Подробнее об этой ошибке.
attempt to index nil with 'Name'Код прочитал что-то, здесь .Name, у значения nil. В примере выше player был nil, потому что площадки коснулся свободный парт.Выясните, почему значение nil, и проверяйте его через if перед использованием. Подробнее об этой ошибке.
Expected 'end' (to close 'then' at line 2), got <eof>У if на строке 2 нет парного end. Для функции сообщение говорит to close 'function', а <eof> значит конец файла.Добавьте пропущенный end, ориентируясь на строку в скобках, а не на последнюю. Иногда сообщение заканчивается фразой «did you forget to close ... at line N?». Это догадка Luau по отступам, и она может указывать не на тот блок, поэтому сначала проверьте строку в скобках. Подробнее о синтаксических ошибках.

Если скрипт ничего не делает и Output тоже пуст, обычно скрипт лежит там, где никогда не запускается, или ждёт события, которое не срабатывает. В гайде по ошибкам есть чек-лист для молчащих скриптов и подробнее о чтении Output (на английском).

Что старые туториалы по скриптингу делают иначе

Если вы учитесь ещё и по видео и постам на форумах, вам встретятся старые шаблоны. Вот важные, с причиной, почему каждый из них проблема.

Шаблоны из старых туториалов и что вместо них делает этот гайд
ТуториалПроблемаЭтот гайд
Делает паузу через wait(1)Справочник Roblox помечает глобальный wait() устаревшим и говорит, что его заменил task.wait().task.wait(1)
Находит персонажа через otherPart.Parent, как в уроке Roblox про лавуКогда парта касается шляпа или инструмент в руке, otherPart.Parent это Accessory или Tool, а не персонаж, поэтому Humanoid не находится и касание теряется.FindFirstAncestorOfClass("Model"), затем GetPlayerFromCharacter
Использует Touched без debounceTouched срабатывает несколько раз подряд за один шаг, поэтому код выполняется снова и снова.Флаг busy и перезарядка
Кладёт LocalScript внутрь парта в WorkspaceLocalScript там никогда не запускается. Он работает только из мест, принадлежащих одному игроку.LocalScript в StarterPlayerScripts (почему)
Пишет part.Touched:connect(...) или table.getn(list)Гайд Roblox по именованию говорит, что API в camelCase в основном устарели, а справочник перечисляет только Connect. table.getn устарел в пользу #list.:Connect(...) и #list
Меняет монеты или наносит урон в LocalScriptИзменение остаётся на устройстве этого игрока, поэтому его никто больше не видит и сервер его не учитывает.Правила игры в Script на сервере

Практика: три изменения, которые стоит попробовать

Изменять код учит больше, чем читать его. Попробуйте это в своём плейсе по одному и нажимайте Play после каждого.

  • Пусть площадка даёт очко. Добавьте скрипт Leaderstats из шага 1 гайда по таблице лидеров. Затем в TouchPad после busy = true найдите папку игрока leaderstats и прибавьте 1 к значению Coins. Подсказка: player:FindFirstChild("leaderstats"), затем leaderstats:FindFirstChild("Coins"), затем coins.Value += 1. Площадка с монетами в гайде по таблице лидеров это готовая версия, с перезарядкой для каждого игрока.
  • Пусть ColourChanger ещё и меняет прозрачность. Сделайте так, чтобы ColourChanger каждую секунду менял и Transparency парта. Подсказка: добавьте вторую таблицу чисел от 0 до 1, например { 0, 0.3, 0.6 }, и задавайте из неё part.Transparency на строке после part.Color, с тем же index.
  • Напечатайте цвет площадки. Пусть MyFirstLocalScript печатает Color площадки при нажатии E. Подсказка: print(pad.Color) внутри блока if pad and pad:IsA("BasePart"). Нажмите E, пока площадка жёлтая: клиент видит цвет, заданный сервером, потому что изменения на сервере доходят до всех клиентов.

Что учить дальше

Теперь вы использовали детали, из которых построено большинство игровых скриптов. Хороший порядок дальше:

  1. LocalScript vs Script vs ModuleScript: где работает каждый тип скрипта и что он может менять, глубже, чем шаг 4.
  2. RemoteEvents: как LocalScript просит сервер что-то сделать и как сервер проверяет запрос.
  3. Таблица лидеров: ваши первые характеристики, созданные и изменяемые на сервере.
  4. Ваша первая игра: короткая трасса с лавой, монетами и финишной площадкой на двух серверных скриптах, затем публикация.
  5. Потом выберите систему: GUI магазина, система раундов, чекпоинты в обби, экран загрузки или анимация по нажатию клавиши. Когда что-то ломается, гайд по ошибкам в скриптах помогает прочитать сообщение. Эти гайды на английском.

Собственные туториалы Roblox Coding fundamentals (на английском) хорошо дополняют этот гайд: шесть серий от переменных и функций через условия, циклы, массивы и словари до организации кода в ModuleScript, с маленькими проектами в Studio.

Частые ошибки и решения

Большинство проблем с первыми скриптами это несовпадающее имя, скрипт не в том месте или цикл без ожидания. Держите Output открытым во время теста.

Studio зависает или перестаёт отвечать при нажатии Play

В цикле while true do нет ожидания, поэтому больше ничего не может выполниться. Документация Roblox говорит, что бесконечный цикл без задержки вроде task.wait() вешает игру и роняет Studio. Ставьте task.wait() в каждый бесконечный цикл, как в ColourChanger.

Ничего не происходит, когда я встаю на площадку

Проверьте, что TouchPad это Script, а не LocalScript, лежит прямо внутри парта Pad, не отключён, и что свойство CanTouch у площадки отмечено. Затем сделайте print("touched", otherPart.Name) первой строкой внутри onTouched. Если это не печатается, событие не срабатывает; если печатается, проблема ниже.

Нажатие E ничего не делает

MyFirstLocalScript должен быть LocalScript внутри StarterPlayerScripts: LocalScript в Workspace или ServerScriptService никогда не запускается. Парт должен называться точно Pad и лежать прямо в Workspace. Сначала щёлкните по окну игры и убедитесь, что не печатаете в чате, потому что скрипт игнорирует клавиши, которые игра уже использовала.

Парт меняется на моём экране, но не у других игроков

Изменение сделал LocalScript, поэтому оно осталось на вашем устройстве. Делайте его в серверном Script или пусть LocalScript попросит сервер через RemoteEvent.

ColourChanger работает внутри парта, но ломается в ServerScriptService

Он использует script.Parent как свой парт. В ServerScriptService родитель это ServerScriptService, у которого нет Anchored или Color, поэтому Output показывает ошибку «not a valid member». Держите его внутри парта или дайте парту имя и ищите его по имени, например local part = workspace:WaitForChild("ColourPart") :: BasePart.

Output вообще ничего не показывает

Проверьте, что окно Output открыто (меню Window или вкладка Script) и не стоит фильтр: Output можно фильтровать по типу сообщений, по Client или Server и по тексту. Если оно открыто и всё равно пустое, скрипт, вероятно, не запускался. Смотрите чек-лист для скриптов, которые ничего не делают.

Если застряли: RoCode

Если вы застряли на скрипте в своём плейсе, RoCode может разобрать его вместе с вами. RoCode это независимый ИИ-агент для Roblox Studio, не от Roblox: вы пишете в веб-чате, а его плагин для Studio создаёт и правит скрипты в вашем Explorer.

Пока вы учитесь, полезен режим Ask: скрипты пишете вы, а RoCode читает то, что уже есть, и отвечает на вопросы.

Вы пишете

Объясни построчно, что делает скрипт TouchPad внутри парта Pad, и почему в нём используется debounce.

RoCode делает
  • В режиме Ask использует только инструменты чтения, например Search Scripts и Read Script, и ничего не меняет в плейсе
  • Если что-то нужно исправить, говорит, что и где он бы изменил, и предлагает переключиться на Build
  • В режиме Build правит скрипты на месте, затем проверяет каждый через Check Script. Это проверка компиляции, а не проверка типов и не плейтест
  • Читает Output Studio инструментом Check Output, включая строки Server и Client вашего последнего плейтеста, даже после нажатия Stop

В режиме Build с плагином 3.9 или новее RoCode может запустить короткий плейтест и прочитать ошибки, а с 3.9.11 или новее управлять тестовым персонажем, но во время игры он не делает скриншотов, поэтому на площадку вы всё равно встаёте сами. Как RoCode подключается к Studio.

Частые вопросы

Где писать скрипты в Roblox Studio?

В Explorer наведите курсор на контейнер, например ServerScriptService, нажмите + и выберите Script. Studio откроет его в Script Editor, где вы пишете Luau. Серверные скрипты обычно лежат в ServerScriptService; LocalScript в StarterPlayerScripts или StarterGui.

Как запустить скрипт в Roblox Studio?

Нажмите Play (F5). Studio запустит плейтест, и каждый включённый Script в ServerScriptService или Workspace выполнится сразу при старте игры; LocalScript в StarterPlayerScripts выполнятся, когда вы зайдёте в плейтест. Run (выберите в списке рядом с Play или нажмите F8) запускает игру без аватара, поэтому для этого гайда используйте Play. Stop (Shift+F5) завершает тест. Чтобы открыть существующий скрипт, дважды щёлкните по нему в Explorer.

Какой язык программирования использует Roblox?

Luau. Roblox описывает его как быстрый, маленький, безопасный язык скриптов с постепенной типизацией, произошедший от Lua 5.1, поэтому большинство туториалов по Lua всё ещё полезны. Luau добавляет возможности вроде интерполяции строк в обратных кавычках и необязательных аннотаций типов, а Roblox добавляет свои библиотеки и объекты, например task.wait.

Чем Script отличается от LocalScript?

Script работает на сервере, и его изменения доходят до всех игроков. LocalScript работает на устройстве одного игрока, для ввода, камеры и экранных меню, и его изменения партов, значений и интерфейса остаются на этом устройстве. Гайд о клиенте и сервере (на английском) разбирает оба, плюс ModuleScript.

Можно ли писать скрипты в Roblox Studio на телефоне или iPad?

Страница установки Roblox описывает Studio как бесплатное приложение для Windows и Mac и не называет версии для телефона или планшета, поэтому для скриптов нужен компьютер.

Почему мой скрипт ничего не делает и не показывает ошибку?

Обычно он лежит там, где такой скрипт не запускается (LocalScript в Workspace или Script в StarterPlayerScripts), он отключён или событие, которого он ждёт, не срабатывает. В гайде по ошибкам есть чек-лист.

Сколько времени нужно, чтобы научиться скриптингу в Roblox?

Честного числа никто не назовёт: это зависит от того, сколько вы строите. Больше всего помогает часто писать маленькие скрипты в своём плейсе. Меняйте четыре скрипта отсюда, попробуйте задания для практики, затем пройдите гайд по первой игре и добавляйте по одной системе.

Источники и что почитать

Как проверялся код: каждый скрипт на этой странице проходит строгую проверку типов Luau с определениями Roblox API (luau-lsp, 26 октября 2026 г.). Проверка типов ловит опечатки в API и неверные типы, но не ошибки игровой логики, поэтому протестируйте всё в Studio перед публикацией.

Попробуйте RoCode в своей игре.

Бесплатные кредиты каждый день, без карты. Установите плагин, опишите функцию и проверьте, что появилось в Studio.