Hey Creators,
We’re launching Instance attributes in Studio beta. You can now point an attribute at another Instance directly instead of relying on a separate ObjectValue. This works through a new engine type called InstanceHandle.
What’s new?
Attributes let you store your own data on an instance, a number, a string, a Vector3, and so on. Until now, attributes could only hold plain data. If you wanted a part to point at another part, you had to add an ObjectValue as a child to hold the reference. Now an attribute can point at another Instance directly:
local part = script.Parent
-- Point an attribute at another Instance
part:SetAttribute("Target", workspace.TargetPart)
-- Read it back
local handle = part:GetAttribute("Target")
local target = handle:Get() -- the Instance, or nil if it isn't available right now
if target then
print("Target is", target.Name)
end
You pass an Instance to SetAttribute and it’s stored for you. When you read it back with GetAttribute, you get an InstanceHandle (not the Instance itself – see below). Call Wait() or Get() on the handle to grab the actual Instance.
Why a Handle Instead of the Instance
The short answer is replication. Sometimes, the Instance you’re pointing at might not exist on a client yet. If GetAttribute returned the Instance directly, it would have to return nil when the target isn’t around. But nil is also what you get when the attribute doesn’t exist at all. Those are two different situations, and you’d have no way to tell them apart.
InstanceHandle keeps them separate:
- The attribute doesn’t exist →
GetAttributereturnsnil. - The attribute exists, but the target isn’t here right now →
GetAttributereturns a handle, andhandle:Get()returnsnil.
The handle is also streaming-aware. If the target streams out, Get() starts returning nil. To wait for it instead, use Wait():
local handle = part:GetAttribute("Target")
if handle then
-- get if it's here now, otherwise wait for it to stream in
local target = handle:Wait()
print("Target is", target.Name)
end
Wait() yields until the Instance is available. You can pass a timeout in seconds, and it returns nil if that time passes first.
More Examples
Reacting to changes
GetAttributeChangedSignal fires when the attribute is set to a new target or deleted, so you can react to it:
part:GetAttributeChangedSignal("Target"):Connect(function()
local handle = part:GetAttribute("Target")
if handle then
local target = handle:Get()
if target then
print("New target:", target.Name)
end
end
end)
Note that this signal fires when the attribute itself changes. It does not fire when the referenced Instance streams in or out, or is destroyed.
Sending references over remotes
InstanceHandle isn’t just for attributes. It’s a normal engine type, so you can send it through a RemoteEvent. This is useful when the server sends a reference to an Instance that hasn’t reached the client yet. You send the handle now, and the client waits for the Instance to arrive:
-- Server
remote:FireClient(player, InstanceHandle.new(workspace.Boss))
-- Client
remote.OnClientEvent:Connect(function(handle)
local boss = handle:Wait()
print("Boss:", boss.Name)
end)
API
InstanceHandle
InstanceHandle.new(instance: Instance): InstanceHandle: creates a handle pointing at the given Instance.handle:Get(): Instance?: the Instance if it’s available locally, nil otherwise. Does not yield.handle:Wait(timeout: number?): Instance?: yields until the Instance is available. With a timeout in seconds, returns nil if that time passes first.tostring(handle): the target’s name, or “nil”.handle1 == handle2: true if they point at the same target.
Attributes
Instance:SetAttribute(name, value): now accepts an Instance or an InstanceHandle. An Instance is wrapped for you. Passing nil deletes the attribute.Instance:GetAttribute(name): returns an InstanceHandle if the attribute holds a reference, or nil if the attribute doesn’t exist.Instance:GetAttributes(): reference attributes appear as InstanceHandle values.Instance:GetAttributeChangedSignal(name): fires when the attribute is set to a new target or deleted.
Studio
- Instance is now a type you can pick in the attribute dropdown in the Explorer, using the standard reference picker.
Try it out
Thanks for building with us. Try Instance references in your attributes and let us know how they work for you.


