Instance Manipulation
Every object in the Roblox world is an Instance. Understanding which properties you can read, which you can change, and what effect those changes have is fundamental to scripting.
Reading Properties
Any property visible in Dex can be read:
local part = workspace:FindFirstChild("SomePart")
print(part.Position) -- Vector3
print(part.Size) -- Vector3
print(part.CFrame) -- CFrame (position + rotation combined)
print(part.Transparency) -- 0-1
print(part.Color) -- Color3
print(part.Anchored) -- boolean
print(part.CanCollide) -- boolean
print(part.Material) -- Enum.Material
Client-Side vs Server-Side Changes
Client-side only (only you see it):
- Part position/CFrame changes
- Part color, transparency changes
- Humanoid.WalkSpeed, JumpPower
- Camera properties
- GUI visibility
Affects server (only via remotes):
- Anything that changes game state for everyone
- NPC health, player currency, inventory
If you change humanoid.WalkSpeed = 100 on your character, you move faster on your screen. But the server may desync your position and teleport you back, or kick you for speed violations.
Position and Movement
local hrp = Players.LocalPlayer.Character:WaitForChild("HumanoidRootPart")
-- Teleport to a position
hrp.CFrame = CFrame.new(0, 100, 0)
-- Teleport to another player
local target = Players:FindFirstChild("TargetName")
if target and target.Character then
hrp.CFrame = target.Character.HumanoidRootPart.CFrame + Vector3.new(0, 5, 0)
end
-- Move relative to current position
hrp.CFrame = hrp.CFrame + Vector3.new(10, 0, 0) -- move 10 studs on X axis
-- Face a direction
local targetPos = Vector3.new(100, 0, 100)
hrp.CFrame = CFrame.lookAt(hrp.Position, targetPos)
Teleporting is client-side. Roblox replication will move your visible position, but server-side physics may fight you. Teleporting too far at once often causes a "sanity teleport" back.
CFrame Basics
CFrame (CoordinateFrame) combines position and rotation:
-- Create from position
local cf = CFrame.new(10, 5, 20)
-- Create from position + direction
local cf = CFrame.lookAt(Vector3.new(0,0,0), Vector3.new(1,0,0)) -- look at X+
-- Create from Euler angles (in radians)
local cf = CFrame.Angles(math.rad(90), 0, 0) -- 90 degree pitch
-- Combine: multiply CFrames
local cf = CFrame.new(0, 0, 0) * CFrame.Angles(0, math.rad(45), 0)
-- Extract position and rotation
local pos = cf.Position -- Vector3
local rx, ry, rz = cf:ToEulerAnglesXYZ()
-- Move forward by 5 studs (relative to current rotation)
hrp.CFrame = hrp.CFrame * CFrame.new(0, 0, -5) -- forward in Roblox is -Z
Part Properties
local part = workspace.SomePart
-- Visibility
part.Transparency = 0.5 -- 0 = solid, 1 = invisible
part.Color = Color3.fromRGB(255, 0, 0) -- red
part.Material = Enum.Material.Neon -- glowing material
-- Physics
part.Anchored = true -- can't move (stops physics)
part.CanCollide = false -- no collision
part.Massless = true -- no physics weight
-- Size and shape
part.Size = Vector3.new(4, 4, 4)
Modifying Another Player's Character
You can read other players' characters, and make client-side changes:
local target = Players:FindFirstChild("SomePlayer")
if target and target.Character then
local theirHumanoid = target.Character:FindFirstChildOfClass("Humanoid")
local theirHRP = target.Character:FindFirstChild("HumanoidRootPart")
-- Read their state
print(theirHumanoid.Health, theirHumanoid.WalkSpeed)
print(theirHRP.Position)
-- Client-side only change (visual on your screen)
for _, part in target.Character:GetDescendants() do
if part:IsA("BasePart") then
part.Transparency = 0.5 -- make them semi-transparent (only you see this)
end
end
end
Destroying and Creating Instances
-- Destroy an instance (client-side)
local annoying = workspace:FindFirstChild("AnnoyngPart")
if annoying then annoying:Destroy() end
-- Create and parent a new instance
local highlight = Instance.new("Highlight")
highlight.FillColor = Color3.fromRGB(255, 0, 0)
highlight.OutlineColor = Color3.fromRGB(255, 255, 255)
highlight.Adornee = targetCharacter
highlight.Parent = game:GetService("CoreGui") -- parent to CoreGui so it persists
Detecting Property Changes
Subscribe to changes on any property:
local part = workspace.SomePart
-- GetPropertyChangedSignal: specific property
part:GetPropertyChangedSignal("CFrame"):Connect(function()
print("part moved to", part.Position)
end)
-- Changed: fires for any property change (use sparingly — noisy)
part.Changed:Connect(function(propertyName)
if propertyName == "Transparency" then
print("transparency changed to", part.Transparency)
end
end)
The AncestryChanged Pattern
Detect when an instance is removed from the tree:
local enemy = workspace.Enemies:FindFirstChild("Boss")
if enemy then
enemy.AncestryChanged:Connect(function(child, parent)
if parent == nil then
print("Boss was removed from the game")
end
end)
end
This is useful for tracking enemy deaths, round resets, and other lifecycle events.
ChildAdded / ChildRemoved
React to instances being added or removed from a folder:
local enemyFolder = workspace:WaitForChild("Enemies")
enemyFolder.ChildAdded:Connect(function(newEnemy)
print("New enemy spawned:", newEnemy.Name)
-- Set up ESP for this enemy
end)
enemyFolder.ChildRemoved:Connect(function(removedEnemy)
print("Enemy removed:", removedEnemy.Name)
-- Remove ESP for this enemy
end)
This pattern is how you build dynamic ESP that automatically handles new entities.