{}const=>[]async()letfn</>var
LuaРазработка

Roblox Lua старт: первый скрипт, который двигает объект и реагирует на игрока 🕹️

Разбираемся с Luau в Roblox Studio с нуля: пишем три рабочих скрипта — движение объекта по синусоиде, реакция на касание игрока и комбо-скрипт с анимацией и сменой цвета. Без воды, с мемами и шпаргалкой по синтаксису. Идеально для тех, кто хочет попробовать геймдев, но не знает, с чего начать.

К

Кодик

Автор

7 мин чтения

«Я просто хотел подвинуть кубик… а в итоге написал игру на 200 строк» - каждый, кто открыл Roblox Studio

Зачем вообще Lua в Roblox?

Окей, давай разберёмся. Ты наверняка слышал про Roblox - платформу, где миллионы людей играют в игры, которые создали… другие игроки. И вот за всей этой магией стоит Luau - это форк Lua, заточенный под Roblox. Быстрый, простой, с типами (ну, почти).

Если ты уже кодишь на JS, Python или чём-то ещё - Lua покажется тебе подозрительно простым. Никаких {} для блоков, никаких ; в конце строк. Просто local, function, end и поехали.

Факт: массивы в Lua начинаются с 1, а не с 0. Да, мы тоже в шоке. Не благодарите.

Розовый геймпад крупным планом, позади блочные персонажи Roblox на неоновой дорожке
🔥 100 000+ учеников уже с нами

Устал читать теорию?
Пора кодить!

Кодик — приложение, где ты учишься программировать через практику. AI-наставник, интерактивные уроки, реальные проекты.

🤖 AI 24/7
🎓 Сертификаты
💰 Бесплатно
🚀 Начать учиться
Присоединились сегодня

Шаг 0: Открываем Roblox Studio

  1. Качаем Roblox Studio

  2. Создаём новый проект → выбираем Baseplate (пустой мир с полом)

  3. Видим 3D-сцену, слева - Explorer (дерево объектов), справа - Properties

Всё. Ты - разработчик игр. Можешь обновлять LinkedIn.

Шаг 1: Кидаем объект на сцену

В меню сверху жмём Part → на сцене появляется серый кирпич. Это наш подопытный.

Переименуем его для порядка:

  • В Explorer находим Part

  • Кликаем правой кнопкой → Rename → пишем MovingBlock

Можно поменять цвет в PropertiesBrickColor. Чисто для вайба.

Шаг 2: Первый скрипт - двигаем объект

Теперь самое интересное. Кликаем правой кнопкой по MovingBlock в Explorer → Insert ObjectScript.

Открывается редактор кода. Удаляем дефолтный print("Hello world!") и пишем:

local block = script.Parent  -- это наш MovingBlock
local startPos = block.Position  -- запоминаем стартовую позицию

while true do
    for i = 0, 10, 0.1 do
        block.Position = startPos + Vector3.new(math.sin(i) * 5, 0, 0)
        task.wait(0.03)
    end
end

Что тут происходит:

  • script.Parent - это объект, внутри которого лежит скрипт (наш блок)

  • Vector3.new(x, y, z) - координаты в 3D пространстве

  • math.sin(i) * 5 - блок качается туда-сюда по синусоиде с амплитудой 5 юнитов

  • task.wait(0.03) - пауза между кадрами (≈30 FPS движения)

Жмём Play (зелёная кнопка сверху) и… кубик поехал! Туда-сюда, как маятник. Красота.

Поздравляю, ты только что написал свой первый игровой скрипт. Это уже больше, чем делает 90% людей, которые «хотят делать игры».

Шаг 3: Реагируем на игрока - «не трогай мой кубик!»

Теперь сделаем так, чтобы блок реагировал, когда игрок его касается. Заменяем содержимое скрипта на:

local block = script.Parent
local startPos = block.Position
local isRunning = false

-- Функция: блок убегает вверх при касании
local function onTouch(otherPart)
    -- Проверяем, что нас коснулся именно игрок (у него есть Humanoid)
    local humanoid = otherPart.Parent:FindFirstChild("Humanoid")

    if humanoid and not isRunning then
        isRunning = true

        -- Блок подпрыгивает
        for i = 0, 3, 0.1 do
            block.Position = startPos + Vector3.new(0, math.sin(i) * 8, 0)
            task.wait(0.02)
        end

        -- Возвращается на место
        block.Position = startPos

        -- Кулдаун 1 секунда
        task.wait(1)
        isRunning = false
    end
end

-- Подписываемся на событие касания
block.Touched:Connect(onTouch)

Разбор полётов:

  • Touched - событие, которое срабатывает при физическом контакте с объектом

  • :Connect(функция) - подписка на событие (привет, паттерн Observer!)

  • FindFirstChild("Humanoid") - проверяем, что нас коснулся игрок, а не случайный кирпич

  • isRunning - флаг-дебаунс, чтобы анимация не запускалась 100 раз подряд

Нажми Play, подойди к блоку персонажем, коснись его - и он подпрыгнет. Как кот, которого напугали огурцом.

Блочный персонаж с геймпадом стоит перед светящимся розовым блоком на платформе

Шаг 4: Комбо - движение + реакция

А теперь финальный босс. Сделаем блок, который и двигается сам, и реагирует на игрока - меняет цвет и раздувается:

local block = script.Parent
local startPos = block.Position
local originalColor = block.BrickColor
local isReacting = false

-- Движение блока (в отдельном потоке)
task.spawn(function()
    while true do
        for i = 0, 10, 0.1 do
            if not isReacting then
                block.Position = startPos + Vector3.new(
                    math.sin(i) * 5, 0, math.cos(i) * 5
                )
            end
            task.wait(0.03)
        end
    end
end)

-- Реакция на касание
block.Touched:Connect(function(otherPart)
    local humanoid = otherPart.Parent:FindFirstChild("Humanoid")

    if humanoid and not isReacting then
        isReacting = true

        -- Меняем цвет на случайный
        block.BrickColor = BrickColor.Random()
        block.Size = block.Size + Vector3.new(1, 1, 1)

        task.wait(0.5)

        -- Возвращаем как было
        block.BrickColor = originalColor
        block.Size = block.Size - Vector3.new(1, 1, 1)

        task.wait(0.5)
        isReacting = false
    end
end)

print("🎮 Скрипт запущен! Попробуй коснуться блока.")

Что нового:

  • task.spawn() - запускает функцию асинхронно (как горутина, только в Lua)

  • Блок двигается по кругу: sin по X, cos по Z - круговая траектория

  • При касании блок меняет цвет на случайный и «раздувается»

  • print() выводит сообщение в Output (View → Output в Studio)

Теперь у нас есть блок, который летает по кругу и троллит игрока вспышками цвета при касании. По сути - это уже мини-игра «поймай кубик».

Быстрая шпаргалка

Концепт

Пример

Переменная

local x = 42

Функция

local function greet(name) return "Привет, " .. name end

Условие

if x > 0 then ... elseif x == 0 then ... else ... end

Цикл

for i = 1, 10 do ... end

Таблица (массив)

local arr = {1, 2, 3} - индексы с 1!

Таблица (объект)

local obj = {name = "Block", hp = 100}

Событие

object.Event:Connect(function() end)

Ожидание

task.wait(1) - пауза 1 секунда

Асинхронность

task.spawn(function() ... end)

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

Ты написал свой первый скрипт - респект. Но это только начало:

  • RemoteEvents - общение между клиентом и сервером (да, в Roblox есть клиент-серверная архитектура!)

  • DataStoreService - сохранение прогресса игроков

  • TweenService - плавные анимации без ручных циклов

  • UI - интерфейсы с помощью ScreenGui

  • Модули - ModuleScript для чистой архитектуры

📱 Хочешь прокачать навыки программирования?

Если тебя зацепила тема и хочется не просто читать, а реально кодить - попробуй приложение Кодик. Это платформа, где программирование изучается через практику: короткие уроки, задачи с проверкой прямо в приложении и понятные объяснения без воды. Идеально, чтобы подтянуть основы или освоить новый язык в метро, в очереди или перед сном.

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


Удачи в геймдеве! И помни: каждая AAA-игра когда-то начиналась с кубика, который кто-то пнул скриптом. 🎮

Вопросы про движущийся блок и Touched

Как заставить деталь двигаться в Roblox Studio?

Деталь двигают скриптом, который меняет её свойство Position в цикле. В примере из статьи блок качается по синусоиде: block.Position = startPos + Vector3.new(math.sin(i) * 5, 0, 0), а task.wait(0.03) держит паузу между кадрами. Стартовую позицию запоминают заранее, иначе блок будет уезжать всё дальше.

Как понять, что детали коснулся именно игрок?

Игрока в обработчике Touched определяют по наличию Humanoid: otherPart.Parent:FindFirstChild("Humanoid"). Если Humanoid найден, касание сделал персонаж. Без такой проверки событие сработает от любого кирпича, который просто упал рядом.

Зачем нужен дебаунс в обработчике Touched?

Дебаунс нужен потому, что Touched срабатывает много раз подряд, пока персонаж соприкасается с деталью. Обычный приём: булев флаг вроде isRunning, который ставят в true в начале реакции и возвращают в false после паузы. Так анимация не запустится сто раз за секунду.

Как объект может двигаться и одновременно реагировать на касание?

Бесконечный цикл движения запускают отдельно через task.spawn(function() ... end), а на Touched вешают свой обработчик. task.spawn выполняет функцию асинхронно, поэтому цикл не блокирует остальной код скрипта. Общий флаг вроде isReacting помогает притормозить движение на время реакции.

Чем Luau отличается от обычного Lua?

Luau это форк Lua, который Roblox заточил под свою платформу: он быстрый, простой и поддерживает типы. Синтаксис остался узнаваемым: фигурные скобки для блоков не нужны, точка с запятой в конце строки тоже, есть local, function и end.

С какого числа начинаются индексы массивов в Lua?

Индексы массивов в Lua начинаются с 1, а не с нуля. После JavaScript или Python об этом легко забыть и промахнуться на один элемент. Поэтому перебор пишут как for i = 1, #arr do.

🎯Хватит откладывать

Понравилась статья?
Пора применять на практике!

В Кодик ты не просто читаешь — ты сразу пишешь код. Теория + практика = реальный скилл.

Мгновенная практика
🧠AI объяснит код
🏆Сертификат

Без регистрации • Без карты