LOADING
OPENING STUDIO

Home / Tutorials / Roblox Studio & Luau

Gaming // Build & Code

Roblox Studio & Luau

Roblox Studio is the free tool you build games in — and Luau is the language you script them with. This is the beginner path: get set up, learn the windows, make your first Part, then make it do something with code.

01 Get Roblox Studio +

Roblox Studio is free on PC and Mac. Grab it from create.roblox.com (Start Creating → download), sign in with your Roblox account, and open it.

On the New screen, pick a template. Start with Baseplate — it's an empty flat world, perfect for messing around without anything getting in the way.

02 The interface — four windows that matter +

Studio throws a lot at you, but as a beginner you mostly live in four panels:

Explorer

The tree of everything in your game. Workspace holds the 3D world; parts, models, and scripts all sit somewhere in here. If it's hidden: View → Explorer.

Properties

Click anything in the Explorer and its settings show here — size, color, position, and dozens more. This is where you tweak stuff by hand.

Toolbox

Free models, images, and sounds other people made. Handy, but drop things in carefully — some free models carry junk scripts.

Output

View → Output. This is where your code's print() messages and errors appear. Keep it open the moment you start scripting.

03 Your first Part +

A Part is a single building block — a brick. On the Home or Model tab, click Part to drop one into the world.

  • Move / Scale / Rotate — the tools on the Model tab (or press R, T handles). Drag the arrows to position it.
  • Select the Part and look at Properties. Three to know right away:

Anchored

When true, the part is frozen in place and won't fall or get pushed. Turn this on for floors and platforms.

Color / Material

Repaint it and change what it's "made of" (Plastic, Neon, Wood…).

Transparency

0 is solid, 1 is invisible. 0.5 is see-through.

04 Scripts & where they live +

Code goes in scripts, and scripts sit in the Explorer. There are three kinds, and putting them in the right place matters:

Script (server)

Runs on the server — the shared game everyone is in. Put these in ServerScriptService (or on a part in the Workspace). Use for game rules, spawning, scoring.

LocalScript (client)

Runs on one player's device. Put these in client spots like StarterPlayerScripts, StarterGui, or StarterPack. Use for UI, camera, input.

ModuleScript

Doesn't run on its own — it holds reusable code that other scripts require(). Great once you start repeating yourself.

To add one: hover a container in the Explorer, click +, and choose Script. A new script opens with print("Hello world!") already in it.

05 Luau basics — variables & Output +

Luau is Roblox's language (a fast, safe version of Lua). A variable stores a value — always start it with local:

local health = 100        -- a number
local playerName = "Alice"  -- a string (text)
local isAlive = true      -- a boolean (true/false)

print(playerName)          -- shows "Alice" in Output

Press Play (or run the script) and watch the Output window. print() is how you check what your code is doing — you'll use it constantly.

06 Change a Part with code +

You reach into the game with dot notation — walk down the Explorer tree with dots. Put a Part named Part in the Workspace, then in a Script:

local part = game.Workspace.Part

part.Anchored = true
part.Transparency = 0.5
part.Color = Color3.fromRGB(255, 77, 46)  -- R,G,B 0–255
Gotcha

Use Color3.fromRGB(255, 77, 46) for normal 0–255 colors. There's also Color3.new(1, 0.3, 0.18), but that one takes values from 0 to 1 — mixing them up is the classic beginner bug.

07 Functions & events +

A function is a reusable block of code:

local function takeDamage(amount)
    health = health - amount
    print("Health: " .. health)  -- .. joins text
end

takeDamage(10)

An event lets the game call your function when something happens. The classic one is Touched — fires when something bumps a part:

local part = game.Workspace.Part

part.Touched:Connect(function(hit)
    part.Color = Color3.fromRGB(72, 202, 228)  -- turn cyan when touched
end)

:Connect(...) means "when this event fires, run this function." That single pattern powers a huge amount of Roblox games.

08 If statements & loops +

If makes decisions:

if health <= 0 then
    print("You lost!")
elseif health < 50 then
    print("Low health!")
else
    print("Healthy")
end

Loops repeat things:

-- count 1 to 5
for i = 1, 5 do
    print(i)
end

-- keep going while a condition holds
while health > 0 do
    takeDamage(1)
    wait(1)  -- pause 1 second so it doesn't freeze
end
Tip

A while loop with no wait() can freeze Studio. Always give long loops a small pause.

09 Test & publish +
  • Test: hit the Play button (or F5) to drop your avatar into the game and try it. Shift+F5 stops.
  • Save vs publish: File → Publish to Roblox puts it online so friends can play. Give it a name, set it to public, and share the link.
  • Iterate in small steps: change one thing, press Play, check Output, repeat. That loop is the whole job.
Going further
10 Leaderstats & saving data +

leaderstats is a magic name: make a Folder called exactly leaderstats inside a player, drop IntValue/StringValue children in it, and Roblox shows them on the in-game leaderboard automatically. Use a server Script in ServerScriptService:

local Players = game:GetService("Players")

Players.PlayerAdded:Connect(function(player)
    local stats = Instance.new("Folder")
    stats.Name = "leaderstats"   -- must be this exact name
    stats.Parent = player

    local coins = Instance.new("IntValue")
    coins.Name = "Coins"
    coins.Parent = stats
end)

To make it stick between sessions, save with a DataStore. First turn it on: File → Experience Settings → Security → Enable Studio Access to API Services. Then, in a server Script:

local DataStoreService = game:GetService("DataStoreService")
local store = DataStoreService:GetDataStore("PlayerData")

-- load (after you make the leaderstats)
local ok, saved = pcall(function()
    return store:GetAsync("User_" .. player.UserId)
end)
if ok and saved then coins.Value = saved end

-- save when they leave
Players.PlayerRemoving:Connect(function(player)
    pcall(function()
        store:SetAsync("User_" .. player.UserId, player.leaderstats.Coins.Value)
    end)
end)
Two must-dos

Always wrap GetAsync/SetAsync in pcall() (the network can fail), and add a game:BindToClose() save for server shutdowns. DataStores only work from a server Script, never a LocalScript.

11 Make a simple GUI +

On-screen menus live in StarterGui — each player gets their own copy. The nesting is ScreenGui → Frame → TextLabel / TextButton. You can build it by clicking (Insert → ScreenGui, then add a TextButton) or in a LocalScript:

-- LocalScript inside StarterGui
local gui = Instance.new("ScreenGui")
gui.Parent = script.Parent

local btn = Instance.new("TextButton")
btn.Size = UDim2.new(0, 200, 0, 50)          -- 200 x 50 pixels
btn.Position = UDim2.new(0.5, -100, 0.5, -25)  -- centered
btn.Text = "Click me"
btn.Parent = gui

btn.MouseButton1Click:Connect(function()
    btn.Text = "Clicked!"
end)
Reading UDim2

UDim2.new(xScale, xOffset, yScale, yOffset)scale is a fraction of the screen (0.5 = halfway), offset is exact pixels. Mixing them (like 0.5, -100) is how you center things on any screen size.

12 Tweening & animation +

TweenService smoothly slides a property from its current value to a goal over time — no loops needed. Three parts: the instance, a TweenInfo (duration + easing), and a table of goals.

local TweenService = game:GetService("TweenService")
local part = workspace.Part

local info = TweenInfo.new(1.5, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local goal = { Position = Vector3.new(0, 10, 0), Transparency = 0.5 }

local tween = TweenService:Create(part, info, goal)
tween:Play()

It works on almost anything with a number/Color/Vector/UDim2 property — so you can tween a GUI Frame's Position, Size, or BackgroundColor3 the exact same way. Control it with :Play(), :Pause(), and :Cancel().

13 RemoteEvents — client ↔ server +

The client (a LocalScript) and the server (a Script) are separate and can't touch each other's variables directly. A RemoteEvent passes messages between them. Put the RemoteEvent in ReplicatedStorage so both sides can see it.

Client → server — the client calls FireServer(); the server listens with OnServerEvent (its first argument is always the player):

-- LocalScript (client)
local rs = game:GetService("ReplicatedStorage")
rs.GiveCoin:FireServer()

-- Script (server)
local rs = game:GetService("ReplicatedStorage")
rs.GiveCoin.OnServerEvent:Connect(function(player)
    player.leaderstats.Coins.Value += 1
end)

Server → client — the server calls FireClient(player) or FireAllClients(); the client listens with OnClientEvent.

Security — never trust the client

A hacked client can fire any RemoteEvent it wants. The server is the source of truth: before you hand out that coin, check the request is legit (did they really pick it up? is the cooldown done?). Never just do what the client asks.

14 ModuleScripts & reusable code +

Once you catch yourself copy-pasting the same code, it's time for a ModuleScript. It doesn't run on its own — it returns a table (usually of functions) that other scripts load with require(). Store it in ReplicatedStorage so both server and client can use it.

-- ModuleScript in ReplicatedStorage, named "Utils"
local Utils = {}

function Utils.double(n)
    return n * 2
end

return Utils
-- any Script or LocalScript
local rs = game:GetService("ReplicatedStorage")
local Utils = require(rs:WaitForChild("Utils"))

print(Utils.double(5))   --> 10
Why bother

Write a thing once, use it everywhere. require() runs the module once and caches it, so every script shares the same copy — great for shared settings and helper functions.

15 Sounds & particle effects +

Sound: put a Sound inside a part (so it plays from that spot) or in workspace for everywhere, point its SoundId at an asset, and :Play() it.

local sound = Instance.new("Sound")
sound.SoundId = "rbxassetid://9120386436"  -- an audio asset id
sound.Parent = workspace.Part
sound:Play()

Particles: a ParticleEmitter inside a part sprays particles while Enabled, or you can fire a one-off burst with :Emit().

local fx = Instance.new("ParticleEmitter")
fx.Rate = 20
fx.Lifetime = NumberRange.new(1, 2)
fx.Parent = workspace.Part
fx:Emit(15)   -- a single burst of 15
16 Character animations +

Every character has a Humanoid, and animations play through its Animator. You make the animation in Studio's Animation Editor (pose a rig across keyframes, then export — that gives you an AnimationId). Then load and play it:

local anim = Instance.new("Animation")
anim.AnimationId = "rbxassetid://507771019"  -- your exported animation

local humanoid = character:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild("Animator")
local track = animator:LoadAnimation(anim)
track:Play()
Tip

You can only publish animations to a rig you own the rights to, and the AnimationId only works once you've exported it from the Animation Editor.

17 Monetization — passes & products +

Selling things runs through MarketplaceService. Two kinds:

  • Game pass — a one-time, permanent purchase (VIP, a special tool).
  • Developer product — bought repeatedly (coins, potions, revives).

Create either on the Creator Hub → Monetization first to get its ID. For a game pass, check ownership and prompt a purchase:

local Marketplace = game:GetService("MarketplaceService")
local PASS_ID = 00000000

-- does the player already own it?
local ok, owns = pcall(function()
    return Marketplace:UserOwnsGamePassAsync(player.UserId, PASS_ID)
end)
if ok and owns then
    -- give the VIP perk
end

-- offer to buy it
Marketplace:PromptGamePassPurchase(player, PASS_ID)
Server is boss

Check ownership on the server. Developer products are granted in MarketplaceService.ProcessReceipt, which both hands over the item and confirms the sale — never trust the client for purchases.

Guide complete ✓

That's the whole toolkit.

Setup, scripting, saving data, UI, animation, remotes, reusable code and monetization — enough to build and ship a real Roblox game. Now go make something and show a friend.