Roblox API Essentials
These are the services and APIs you'll use in almost every script. Learn these well — everything else builds on top of them.
Getting Services
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")
local CoreGui = game:GetService("CoreGui")
local HttpService = game:GetService("HttpService")
Players Service
local Players = game:GetService("Players")
-- The local player (you)
local me = Players.LocalPlayer
-- All connected players
for _, player in Players:GetPlayers() do
print(player.Name, player.UserId)
end
-- React to players joining/leaving
Players.PlayerAdded:Connect(function(player)
print(player.Name .. " joined")
end)
Players.PlayerRemoving:Connect(function(player)
print(player.Name .. " left")
end)
The LocalPlayer object gives you:
.Name— username.UserId— numeric ID.Character— their character model (or nil if not spawned).CharacterAdded— fires when a new character spawns.Team— their Team object.DisplayName— display name (may differ from Name)
Characters and Humanoids
The character is a Model in workspace containing the player's body parts:
local me = Players.LocalPlayer
local char = me.Character or me.CharacterAdded:Wait()
-- Key parts
local hrp = char:WaitForChild("HumanoidRootPart") -- position/movement
local humanoid = char:WaitForChild("Humanoid")
local head = char:WaitForChild("Head")
-- Humanoid properties
print(humanoid.Health) -- current HP
print(humanoid.MaxHealth) -- max HP
humanoid.WalkSpeed = 50 -- movement speed (client-only change)
humanoid.JumpPower = 100 -- jump height (client-only)
-- Humanoid states
humanoid.Died:Connect(function()
print("I died")
end)
humanoid.StateChanged:Connect(function(old, new)
print("state:", new) -- e.g. "Running", "Jumping", "Freefall"
end)
Getting another player's character:
local target = Players:FindFirstChild("TargetName")
if target and target.Character then
local theirHRP = target.Character:FindFirstChild("HumanoidRootPart")
end
Workspace
local ws = game.Workspace -- or workspace (global shorthand)
-- Camera
local cam = ws.CurrentCamera
print(cam.CFrame) -- where the camera is
print(cam.FieldOfView) -- FOV in degrees
cam.FieldOfView = 90 -- change it (client-only)
-- World properties
ws.Gravity = 196.2 -- default is 196.2
-- Finding things
ws:FindFirstChild("Name") -- returns child or nil
ws:WaitForChild("Name", timeout) -- waits up to timeout seconds
ws:GetChildren() -- direct children only
ws:GetDescendants() -- all descendants (slow on large worlds)
Instance API
These work on any Instance (parts, models, scripts, etc.):
local inst = someInstance
-- Finding children
inst:FindFirstChild("Name") -- nil if not found
inst:FindFirstChildOfClass("Humanoid") -- by class name
inst:FindFirstChildWhichIsA("BasePart") -- class or subclass
inst:WaitForChild("Name") -- yields until found
inst:WaitForChild("Name", 5) -- timeout after 5s
-- Checking
inst:IsA("Model") -- true if Model or subclass
inst.ClassName -- exact class: "Model", "Part", "RemoteEvent"
inst.Name -- instance name
inst.Parent -- parent instance
inst:GetFullName() -- "workspace.PlayerName.HumanoidRootPart"
-- Tree traversal
inst:GetChildren() -- array of direct children
inst:GetDescendants() -- all descendants (can be thousands)
RunService
RunService gives you per-frame events:
local RS = game:GetService("RunService")
-- Heartbeat: fires every frame AFTER physics (most common for scripts)
RS.Heartbeat:Connect(function(deltaTime)
-- deltaTime is seconds since last frame (~0.016 at 60fps)
end)
-- RenderStepped: fires every frame BEFORE rendering (use for camera)
RS.RenderStepped:Connect(function(deltaTime)
end)
-- Stepped: fires every frame BEFORE physics
RS.Stepped:Connect(function(time, deltaTime)
end)
-- BindToRenderStep: lets you control render order with priority
RS:BindToRenderStep("MyStep", Enum.RenderPriority.Camera.Value + 1, function(dt)
end)
-- Cleanup: RS:UnbindFromRenderStep("MyStep")
Use Heartbeat for most per-frame logic (ESPs, loops). Use RenderStepped or BindToRenderStep when you need to run just before the frame renders (camera, aim).
UserInputService
local UIS = game:GetService("UserInputService")
-- Key/mouse events
UIS.InputBegan:Connect(function(input, gameProcessed)
-- gameProcessed = true if Roblox UI consumed the input (e.g. chat box)
if gameProcessed then return end
if input.KeyCode == Enum.KeyCode.E then
print("E pressed")
end
if input.UserInputType == Enum.UserInputType.MouseButton1 then
print("Left click")
end
end)
UIS.InputEnded:Connect(function(input, gameProcessed)
-- key/button released
end)
-- Continuous check (use in loops)
if UIS:IsKeyDown(Enum.KeyCode.LeftShift) then
-- shift is held
end
-- Mouse position
local mousePos = UIS:GetMouseLocation() -- Vector2, screen pixels
Mouse Object
The player's mouse gives you world-space information:
local mouse = Players.LocalPlayer:GetMouse()
-- Where the mouse points in 3D space
print(mouse.Hit) -- CFrame (position + rotation)
print(mouse.Hit.Position) -- Vector3
-- What instance the mouse is over
print(mouse.Target) -- Instance or nil
-- Screen position
print(mouse.X, mouse.Y) -- screen pixels
-- Ray from camera through mouse
local ray = workspace:Raycast(
mouse.UnitRay.Origin,
mouse.UnitRay.Direction * 1000,
RaycastParams.new()
)
Camera
local cam = workspace.CurrentCamera
-- Read camera state
print(cam.CFrame) -- position + orientation
print(cam.FieldOfView) -- FOV degrees
print(cam.CameraType) -- "Custom", "Scriptable", etc.
-- World to screen conversion (essential for ESP)
local screenPos, onScreen = cam:WorldToViewportPoint(worldPos)
-- screenPos.X, screenPos.Y = screen coordinates
-- screenPos.Z > 0 means in front of camera (visible)
if onScreen and screenPos.Z > 0 then
-- draw something at screenPos.X, screenPos.Y
end
-- Screen to world ray
local ray = cam:ViewportPointToRay(screenPos.X, screenPos.Y)
Events: Connect, Disconnect, Once, Wait
local connection = someEvent:Connect(function(...)
-- fires every time event fires
end)
-- Disconnect when done
connection:Disconnect()
-- Fire once, then auto-disconnect
someEvent:Once(function(...)
end)
-- Yield until event fires, returns the event arguments
local arg1, arg2 = someEvent:Wait()
Store connections when you need to clean them up:
local connections = {}
table.insert(connections, RS.Heartbeat:Connect(myFn))
table.insert(connections, UIS.InputBegan:Connect(myOtherFn))
-- Cleanup all at once
for _, conn in connections do
conn:Disconnect()
end
connections = {}
CoreGui
CoreGui is the Roblox system UI layer. You can parent your own UI here — it persists across character respawns and isn't destroyed when the game resets player GUIs:
local CoreGui = game:GetService("CoreGui")
local container = Instance.new("ScreenGui")
container.Name = "MyContainer"
container.ResetOnSpawn = false
container.Parent = CoreGui -- only executors can do this
This is where you should parent ESP highlights and billboard labels so they don't get destroyed when your character reloads.