Коротко
Чтобы написать скрипт в 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.
На этой странице
Перед началом: Studio, Baseplate и окно Output
Нужны Roblox Studio и аккаунт Roblox, и больше ничего: ни редактора кода, ни плагина. Каждый скрипт этого гайда набирается в собственном Script Editor Studio.
- Установите Roblox Studio, бесплатное приложение Roblox для Windows и Mac, и войдите через аккаунт Roblox.
- Откройте Studio. На стартовой странице есть шаблоны: выберите Baseplate. Вы получите пол с текстурой сетки 4x4 и SpawnLocation, место, где появляется ваш аватар при игре.
- Если окна Explorer и Properties не видны, откройте их из меню Window или вкладки Home. Explorer перечисляет все объекты плейса; Properties показывает настройки выделенного.
- Откройте Output из меню Window или вкладки Script. Здесь появляются сообщения и ошибки ваших скриптов.
- В настройках отображения окна Output включите Show Context, который помечает каждое сообщение как Client или Server, и Show Source, который показывает скрипт и номер строки, откуда оно пришло.
| Скрипт | Тип | Где лежит | Чему учит |
|---|---|---|---|
FirstScript | Script | ServerScriptService | Переменные, функция, условие if, циклы и таблица |
ColourChanger | Script | Внутри Part в Workspace | Изменение свойств, script.Parent и цикл с ожиданием |
TouchPad | Script | Внутри Part с именем Pad | События, поиск игрока, коснувшегося парта, и debounce |
MyFirstLocalScript | LocalScript | StarterPlayerScripts, внутри StarterPlayer | Код на устройстве одного игрока, нажатия клавиш и что остаётся на этом устройстве |
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: напишите первый скрипт
- В Explorer наведите курсор на ServerScriptService, нажмите + и выберите Script (сочетание Ctrl+I или ⌘I на Mac). Studio создаст скрипт и откроет его в Script Editor.
- Нажмите на новый скрипт правой кнопкой, выберите Rename и назовите его
FirstScript. Имя не меняет того, что делает скрипт, но говорит, какой скрипт что напечатал. - Новые скрипты начинаются с одной строки,
print("Hello world!"). Удалите её и вставьте код ниже. - Нажмите Play (F5), выбрав Test в списке слева от неё. Studio запустит плейтест и поставит аватар на SpawnLocation.
- Прочитайте строки в Output, затем нажмите Stop (Shift+F5). Stop также возвращает все объекты в состояние до нажатия Play, поэтому всё, что вы сдвинули или перекрасили во время игры, вернётся.
-- 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 с номером строки.
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 в браузере. Поменяйте там значение и запустите снова, чтобы увидеть, что изменится.
| Код | Идея | Что это значит |
|---|---|---|
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 | Условие if | Luau проверяет условия сверху вниз и выполняет только первое истинное. 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 у парта, это свойства, и скрипт тоже может их задавать.
- На вкладке Home нажмите Part. Studio добавит блок в Workspace. Его имя неважно.
- В Explorer наведите курсор на новый парт, нажмите + и вставьте Script. Переименуйте его в
ColourChangerи замените содержимое кодом ниже. - Нажмите Play. Парт становится красным, затем синим, затем зелёным, меняясь раз в секунду, и начинает снова.
-- 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 называет это событиями. Чтобы выполнить код, когда событие срабатывает, к нему подключают функцию.
- Вставьте ещё один Part и переименуйте его точно в
Pad, с заглавной P. Оставьте его прямо в Workspace, не в папке и не в модели, потому что LocalScript на шаге 4 ищет его там. - Сделайте его плоской площадкой, на которую можно встать, например задайте
Sizeравным6, 1, 6в окне Properties. Поставьте его на пол рядом со SpawnLocation и отметьте Anchored, чтобы он не двигался. - Наведите курсор на Pad, нажмите +, вставьте Script, переименуйте его в
TouchPadи вставьте код ниже. - Нажмите Play и встаньте на площадку. Она желтеет на 2 секунды, а Output называет ваше имя.
-- 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)
| Код | Что делает |
|---|---|
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 работает на устройстве одного игрока. Нажатия клавиш, камера и экранные меню обрабатываются там, потому что о них знает только это устройство.
- В Explorer раскройте StarterPlayer, наведите курсор на StarterPlayerScripts, нажмите + и вставьте LocalScript. Переименуйте его в
MyFirstLocalScriptи вставьте код ниже. - Нажмите Play. Output покажет
Hello,и ваше имя с пометкой Client. - Щёлкните по окну игры и нажмите E. Площадка становится прозрачнее. Нажмите E снова, чтобы вернуть её.
- Пока плейтест идёт, нажмите переключатель Client/Server в элементах тестирования Studio, чтобы перейти к серверной копии игры. Там площадка непрозрачна: сервер ничего не узнал об изменении.
-- 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 | На сервере | До всех игроков | Правила игры: монеты, урон, двери, раунды, сохранение | ServerScriptService или внутри парта, пока учитесь |
| LocalScript | На устройстве одного игрока | Только на это устройство, кроме движения своего персонажа | Ввод, камера, экранные меню, эффекты для одного игрока | StarterPlayerScripts или StarterGui |
| ModuleScript | На той стороне, которая вызывает для него require() | Туда же, куда и у подключившего скрипта | Код, общий для нескольких скриптов | ReplicatedStorage для обеих сторон, ServerScriptService только для сервера |
Что может изменить читер
Считайте, что читер контролирует всё на своём устройстве. Он может запускать свои LocalScript и менять ваши, поэтому может сделать прозрачной площадку или что угодно ещё на своём экране. Здесь это безвредно: прозрачность только для вида и остаётся на его устройстве. Именно поэтому всё важное решает Script на сервере.
Серверный Script тоже не безопасен автоматически. TouchPad работает на сервере, но устройство каждого игрока управляет физикой его персонажа, и документация Roblox по безопасности называет среди того, что клиент может делать с подконтрольными партами, управление моментом срабатывания Touched или полную его блокировку. Для светящейся площадки это неважно. Для площадки, которая платит, проверяйте ещё и то, что сервер отслеживает сам, как правило в гайде по обби, что чекпоинты засчитываются только по порядку.
Шаг 5: протестируйте все четыре скрипта вместе
- Очистите Output через Ctrl+K (⌘K на Mac) и нажмите Play (F5). Output покажет восемь строк FirstScript с пометкой Server и вашу строку Hello с пометкой Client. Парт ColourChanger меняет цвет каждую секунду.
- Встаньте на площадку. Она желтеет на 2 секунды, а Output один раз показывает ваше имя и «stepped on the pad». Походите по ней: новая строка появляется не чаще раза в 2 секунды, а не при каждом срабатывании Touched.
- Нажмите E. Площадка становится полупрозрачной (Transparency 0.6). Нажмите E снова, и она непрозрачна.
- Нажмите Stop. В списке тестирования выберите Server & Clients, поставьте 2 клиента и нажмите Play (или F7). Studio откроет окно сервера и два окна клиентов. В одном клиенте нажмите E: площадка станет прозрачнее там, а другой клиент и сервер покажут её непрозрачной. Нажмите End Session, когда закончите.
- Сломайте что-нибудь нарочно. Переименуйте Pad в
Pad2и запустите игру. Шаг на площадку всё ещё делает её жёлтой, потому что TouchPad находит свой парт черезscript.Parent, а не по имени. Нажатие E теперь ничего не делает, и ошибки нет:FindFirstChild("Pad")вернулnil, а проверкаif pad and ...тихо пропустила остальное. Добавьтеprint(pad)на строку послеFindFirstChild, запустите и нажмите E: Output покажетnil. Такой print самый быстрый способ понять, почему скрипт ничего не делает. Остановите игру, удалите строку с print и верните парту имя Pad.
Куда класть скрипты
От того, где лежит скрипт, зависит, запустится ли он вообще, и Studio не предупреждает, если он не запустится никогда. Для следующих ваших скриптов:
| Контейнер | Что класть | Почему |
|---|---|---|
| ServerScriptService | Скрипты с большинством правил игры: награды, раунды, сохранение | Они работают на сервере, и ничего из ServerScriptService не отправляется игрокам. |
| Внутри парта в Workspace | Script, который относится к одному парту, как ColourChanger и TouchPad | Нормально, пока учитесь: парт это script.Parent. Для настоящих проектов Roblox советует вместо этого помечать парты тегами (см. ниже). |
| StarterPlayerScripts, внутри StarterPlayer | Большинство LocalScript: ввод, камера, эффекты для одного игрока | Каждый игрок получает свою копию при входе. |
| StarterGui | LocalScript внутри ScreenGui, которые управляют экранным меню | Каждый игрок получает свою копию интерфейса. |
| ReplicatedStorage | ModuleScript, которые подключает и серверный, и клиентский код | Его видят обе стороны. LocalScript или Script с настройками по умолчанию здесь никогда не запустится. |
Страница Roblox о расположении скриптов советует вообще не класть скрипты прямо в парты в Workspace: пометьте парты тегами и работайте с ними из одного ModuleScript через CollectionService. Скрипт внутри парта всё равно самый простой старт, и для одного-двух объектов, пока вы учитесь, это нормально. Гайд по дверям показывает шаблон с тегами, с одним скриптом на все двери, а гайд о клиенте и сервере содержит полную таблицу, какие контейнеры какие скрипты запускают.
Когда что-то пошло не так: читайте Output
Ошибки показываются в Output красным. Каждая начинается с того, где она произошла, полного имени скрипта и номера строки, а потом говорит, что не так. Нажмите на ошибку, и Studio откроет скрипт на этой строке. Например, если вы удалите проверку if not player из TouchPad, а на площадку упадёт свободный парт, 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 без debounce | Touched срабатывает несколько раз подряд за один шаг, поэтому код выполняется снова и снова. | Флаг busy и перезарядка |
| Кладёт LocalScript внутрь парта в Workspace | LocalScript там никогда не запускается. Он работает только из мест, принадлежащих одному игроку. | 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, пока площадка жёлтая: клиент видит цвет, заданный сервером, потому что изменения на сервере доходят до всех клиентов.
Что учить дальше
Теперь вы использовали детали, из которых построено большинство игровых скриптов. Хороший порядок дальше:
- LocalScript vs Script vs ModuleScript: где работает каждый тип скрипта и что он может менять, глубже, чем шаг 4.
- RemoteEvents: как LocalScript просит сервер что-то сделать и как сервер проверяет запрос.
- Таблица лидеров: ваши первые характеристики, созданные и изменяемые на сервере.
- Ваша первая игра: короткая трасса с лавой, монетами и финишной площадкой на двух серверных скриптах, затем публикация.
- Потом выберите систему: 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.
- В режиме 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?
Честного числа никто не назовёт: это зависит от того, сколько вы строите. Больше всего помогает часто писать маленькие скрипты в своём плейсе. Меняйте четыре скрипта отсюда, попробуйте задания для практики, затем пройдите гайд по первой игре и добавляйте по одной системе.
Источники и что почитать
- Roblox Creator Docs: Luau (на английском). что такое Luau и откуда он
- Roblox Creator Docs: Roblox Studio setup (на английском). Windows и Mac, системные требования
- Roblox Creator Docs: Output (на английском). открытие Output, фильтры, Show Context и Show Source
- Roblox Creator Docs: Studio testing modes (на английском). Play, Run, Stop, переключатель Client/Server и Server & Clients
- Roblox Creator Docs: Script Editor (на английском). где открываются новые скрипты и Script Analysis
- Roblox Creator Docs: Script types and locations (на английском). где работает каждый тип скрипта и теги вместо скриптов в партах
- Roblox Creator Docs: Script (на английском). когда Script начинает работать
- Roblox Creator Docs: Control structures (на английском). условия, циклы и почему бесконечному циклу нужно ожидание
- Roblox Creator Docs: Events (на английском). Connect и что Touched передаёт функции
- Roblox Creator Docs: Debounce patterns (на английском). почему Touched срабатывает несколько раз за одно касание
- Roblox Creator Docs: wait (на английском). глобальный wait() и task.wait()
- Roblox Creator Docs: Network ownership, movement validation and physics exploits (на английском). что клиент может делать со своим персонажем
- Roblox Creator Docs: Coding fundamentals (на английском). серия Roblox для начинающих
Как проверялся код: каждый скрипт на этой странице проходит строгую проверку типов Luau с определениями Roblox API (luau-lsp, 26 октября 2026 г.). Проверка типов ловит опечатки в API и неверные типы, но не ошибки игровой логики, поэтому протестируйте всё в Studio перед публикацией.