Instance.new, Clone() and Attributes in Roblox (Luau Guide)
Last updated:
Quick answer: Instance.new("Part") builds an object from code — configure its properties first and set .Parent last — while Clone() duplicates a template you designed in Studio, and SetAttribute/GetAttribute attach custom data to any instance without Value objects.
Instance.new("Part") builds a brand-new object from code: you pass the class name as a string, configure the properties you care about, and only then set .Parent so the instance enters the game fully built. Clone() duplicates an instance you already have — usually a template you designed in Studio — and SetAttribute / GetAttribute attach your own custom data to any instance without adding Value objects. That trio covers almost everything a beginner creates: parts, GUIs, folders, tools, and per-player copies of them.
How do I create an instance with Instance.new?
Instance.new takes the class name exactly as Roblox spells it — "Part", "Frame", "Folder", "RemoteEvent" — and returns an empty instance that exists only in memory until you parent it.
local part = Instance.new("Part")
part.Name = "SpawnPlatform"
part.Size = Vector3.new(12, 1, 12)
part.Position = Vector3.new(0, 5, 0)
part.Anchored = true
part.Material = Enum.Material.SmoothPlastic
part.Parent = workspace -- parent LAST
Class names are case-sensitive: Instance.new("part") errors, it has to be "Part". The function also accepts an optional second argument that sets the parent immediately — skip it while learning, because it silently breaks the configure-first order that the next section is all about.
Why should I set properties before parenting?
An instance becomes visible to the rest of the game the moment you assign .Parent: scripts can find it, physics starts simulating it, and every property change from then on replicates to clients as a separate network message. Parenting first and configuring after means players can briefly see a default grey block flashing into place at the wrong size and position — and the server sends one message per property instead of one clean spawn.
-- Bad: visible half-configured, replicates every change separately
local part = Instance.new("Part")
part.Parent = workspace
part.Size = Vector3.new(6, 6, 6)
part.Position = Vector3.new(0, 20, 0)
part.BrickColor = BrickColor.new("Bright green")
-- Good: fully built before anyone can see it
local template = Instance.new("Part")
template.Name = "Platform"
template.Size = Vector3.new(6, 6, 6)
template.Position = Vector3.new(0, 20, 0)
template.BrickColor = BrickColor.new("Bright green")
template.Parent = workspace
The same rule applies to anything with children: build the whole subtree, then parent the root once.
How do I find instances that already exist?
Creating is only half the job — most scripts need to reach objects that are already in the game. FindFirstChild returns nil when the instance is missing (so never index the result blindly), and WaitForChild yields until it appears, which is the right tool for objects a script or player is about to load.
local spawnFolder = workspace:FindFirstChild("Spawns")
if not spawnFolder then
warn("No Spawns folder in workspace")
return
end
-- class-based lookup, avoids caring what the instance is named
local function onCharacterAdded(character)
local humanoid = character:WaitForChild("Humanoid")
humanoid.WalkSpeed = 20
end
FindFirstChildOfClass("Humanoid") (and its sibling FindFirstChildWhichIsA) is more robust than searching by name, because players and tools rename things but rarely change class. For deeper, one-time searches workspace:FindFirstChild("A", true) walks the whole tree recursively — fine for setup code, too slow to call every frame.
When should I use Clone() instead of Instance.new?
Use Instance.new when the object is mostly code-shaped (a single part with properties your script decides) and Clone() when the object is design-shaped: a GUI with a dozen nested frames, a tool with meshes and sounds, an arena you built in Studio. The template lives in the place file or in ReplicatedStorage, and one line of code stamps out copies.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local guiTemplate = ReplicatedStorage:WaitForChild("ShopGui")
Players.PlayerAdded:Connect(function(player)
local gui = guiTemplate:Clone()
gui.Name = player.Name .. "_ShopGui"
gui.Parent = player:WaitForChild("PlayerGui")
end)
This is the per-player GUI pattern: keep one template in ReplicatedStorage, clone it for every player, and parent the copy into that player's PlayerGui. The same trick builds arena rounds (clone an arena model per round), enemy waves, or shop stands. Two details to remember: Clone copies properties, attributes, and the whole child tree — and a Script or LocalScript inside a clone starts running once the clone is parented into the DataModel. If you share one instance between players instead of cloning per player, whoever parents it last wins and everyone else sees nothing. When the cloned object should talk to the server, pair it with the RemoteEvents guide.
How do I delete instances — Destroy() or Parent = nil?
They are not the same. Setting Parent = nil only detaches the instance from the tree; every table or variable still holding it keeps it (and its children) alive in memory, and its event connections stay connected. Destroy() is the real delete: it destroys all descendants, disconnects every event connection, and permanently locks the instance so stray code cannot parent it back.
local Debris = game:GetService("Debris")
local coin = Instance.new("Part")
coin.Name = "Coin"
coin.Shape = Enum.PartType.Cylinder
coin.Parent = workspace
-- self-cleaning: gone in 30 seconds, no bookkeeping needed
Debris:AddItem(coin, 30)
-- or delete on demand, e.g. when a player picks it up
local function pickUp(c)
c:Destroy() -- not c.Parent = nil
end
The rule of thumb: Destroy() when you are done with something forever (picked-up coins, finished projectiles), and Debris:AddItem when the object should clean itself up after a timeout. Reserve Parent = nil for temporary removal — pooling an object you will parent again shortly. Destroyed instances raise an error if code tries to use them afterwards, which is exactly what you want: a clear failure instead of a silent ghost object leaking memory.
What are attributes and how do I use them?
Attributes are custom key-value data attached to any instance, visible in the Properties panel and replicated to clients automatically. Set them with SetAttribute, read them with GetAttribute, and react to changes with GetAttributeChangedSignal.
local part = Instance.new("Part")
part:SetAttribute("Health", 100)
part:SetAttribute("TeamColor", Color3.fromRGB(0, 120, 255))
part:SetAttribute("IsLocked", true)
local health = part:GetAttribute("Health") -- 100
print(typeof(health)) -- "number"
part:GetAttributeChangedSignal("Health"):Connect(function()
print("Health is now", part:GetAttribute("Health"))
end)
part:SetAttribute("Health", 75) -- fires the signal above
-- remove an attribute by setting it to nil
part:SetAttribute("IsLocked", nil)
Supported value types are the plain data types — string, boolean, number, Vector3, Vector2, Color3, CFrame, UDim, UDim2, EnumItem, BrickColor and similar. GetAttributes() returns a table of every attribute on the instance, which is handy for saving a whole object's state; feed that table straight into the DataStore guide flow to persist it. Internally, classes built with the setmetatable OOP pattern can read attributes too, since every instance exposes the same API.
Should I use attributes or Value objects?
Older tutorials reach for NumberValue, StringValue, BoolValue, and ObjectValue — child instances whose .Value property holds your data. They still work, but for new code attributes are the modern choice: no extra instances cluttering the explorer, no naming a child "CoinsValue" and finding it with FindFirstChild, and the same replication and change signals.
-- Old style: an extra child instance per value
local coins = Instance.new("NumberValue")
coins.Name = "Coins"
coins.Parent = player
coins.Value = 50
-- Modern style: data on the instance itself
player:SetAttribute("Coins", 50)
local coinsNow = player:GetAttribute("Coins")
Value objects are still the right tool in two cases. First, when you need to store an Instance reference — attributes cannot hold instances or nested tables, so an ObjectValue (or a direct variable in a server module) is the way to point at another object. Second, when legacy code or a specific API expects a Value object child. For flat custom data — counters, flags, cooldowns, team ids — use attributes.
Common mistakes with Instance.new, Clone and attributes
- Parenting before configuring. The instance replicates half-built and every later property set costs an extra network message. Configure, then parent.
- Wrong class-name casing.
Instance.new("part")fails — the string must match the class exactly: "Part", "Model", "ScreenGui". - Using Parent = nil as delete. The instance stays in memory with its connections alive. Call
:Destroy(), orDebris:AddItemfor timed cleanup. - Sharing one cloned object between players. A single GUI parented into one PlayerGui serves one player. Clone the template per player.
- Storing instances or nested tables in attributes.
SetAttributeonly accepts plain data types; use anObjectValueor a module table for references and structured data. - Indexing a FindFirstChild result without a nil check. A renamed or missing instance turns
part.BrickColor = ...into "attempt to index nil". Check, or useWaitForChildfor objects that are still loading.
Learn Luau by doing
Creating and wiring instances only clicks when you have built the spawn loop yourself. On Luablox you can practice Luau interactively through /theory, sharpen the exact APIs above with drills on /problems, and follow structured Luablox lessons that build from Instance.new basics to full gameplay systems.
Frequently asked questions
Why doesn't my Instance.new part appear in the game?
Because it has no Parent yet. An instance created with Instance.new exists only in memory until you set .Parent (usually to workspace). If you did parent it, check that its Position is inside the camera range and that Anchored is set for static parts — otherwise physics may drop it away before anyone sees it.
Should I use Clone() or Instance.new?
Use Instance.new for simple code-shaped objects (a single part whose properties your script decides) and Clone() for design-shaped templates you built in Studio — GUIs, tools, arenas. Clone() also gives you safe per-player copies: keep one template in ReplicatedStorage and clone it into the PlayerGui of each player.
What is the difference between attributes and Value objects?
Attributes store custom data directly on an instance with SetAttribute/GetAttribute, replicate automatically, and need no extra child instances. Value objects (NumberValue, StringValue, ObjectValue) still work and remain useful for Instance references and legacy code, but for flat data like counters and flags attributes are the modern choice.
What is the difference between Destroy() and Parent = nil?
Parent = nil only detaches the instance from the tree; it stays in memory and keeps its event connections as long as anything references it. Destroy() destroys descendants, disconnects all events, and locks the instance permanently. Use Destroy() for real deletion and Debris:AddItem for timed self-cleanup.
Can attributes store Instance references or tables?
No. Attribute values are limited to plain data types like strings, numbers, booleans, Vector3, Color3, and CFrame. For references to other instances use an ObjectValue or a module-level table; for nested data, flatten it into several attributes or keep it in a table you save with a DataStore.
Explore the Roblox DataModel and Instance hierarchy to manipulate workspace parts and services.