Roblox UtilitiesDevlHub Roblox Documentation

Data type

InstanceHandle

A lightweight, weak reference to an Instance that might not be available locally.

The InstanceHandle data type is a weak reference to an Instance that might not be available locally. Use it to point at an instance that hasn't arrived yet, could stream out, or exists only on another machine, and to pick that instance up once it's there.

A handle always refers to the same target. To reach that target, call InstanceHandle:Wait(), which yields until the instance is available:

Luau
local Workspace = game:GetService("Workspace")

local part = Instance.new("Part")
local target = Instance.new("Part")
target.Name = "TargetPart"
part.Parent = Workspace
target.Parent = Workspace

part:SetAttribute("Target", target)

local handle = part:GetAttribute("Target")
local instance = handle:Wait(10)
if instance then
	print("Target is", instance.Name) --> Target is TargetPart
end

Prefer InstanceHandle:Wait() with a timeout so your code runs as soon as the instance shows up. Use InstanceHandle:Get() when you want an immediate answer and can handle nil, such as in code that runs every frame.

Examples#

Attributes#

Attributes use InstanceHandle instead of an ordinary instance reference. Since the handle itself is never nil, you can tell apart an attribute that is missing from one where the instance is not currently present:

Luau
local part = Instance.new("Part")

print(part:GetAttribute("Target")) --> nil

part:SetAttribute("Target", InstanceHandle.new(nil))
local handle = part:GetAttribute("Target")
print(handle:Get()) --> nil

InstanceHandle attributes also appear in Instance:GetAttributes(), which can't hold nil values.

Instance:GetAttributeChangedSignal() fires when the attribute is set to a new target or removed. It does not fire when the target streams in or out, or when the target is destroyed. To react to availability, combine the signal with InstanceHandle:Wait():

Luau
local part = Instance.new("Part")

part:GetAttributeChangedSignal("Target"):Connect(function()
	local handle = part:GetAttribute("Target")
	if not handle then
		return
	end

	local instance = handle:Wait(10)
	if instance then
		print("New target:", instance.Name)
	end
end)
Remote events#

Pass a handle through a RemoteEvent to give the receiver a reference to an instance it doesn't have yet. The receiver waits for the instance instead of getting nothing.

In a server script, call this function with your remote event, the receiving player, and the model to send:

Luau
local function sendHandle(remoteEvent: RemoteEvent, player: Player, spawnedModel: Model)
	local handle = InstanceHandle.new(spawnedModel)
	remoteEvent:FireClient(player, handle)
end

In a client script, call this function with the same remote event to start listening before the server sends the handle:

Luau
local function receiveHandles(remoteEvent: RemoteEvent)
	remoteEvent.OnClientEvent:Connect(function(handle)
		local model = handle:Wait(10)
		if model then
			print("Received", model.Name)
		end
	end)
end

Ownership#

A handle acts as a weak reference. It never keeps its target alive. The lifetime of the target is controlled by the rest of your experience: its parent and any ordinary references your scripts hold that prevent it from being garbage collected.

InstanceHandle:Get() and InstanceHandle:Wait() return an ordinary instance reference, which does keep the instance alive for as long as you hold it.

A handle is otherwise lightweight and needs no cleanup.

Equality#

Two handles are equal when they refer to the same target, even if you created them separately and even after the target is gone. All empty handles are equal to each other. Each handle is still a distinct value.

Luau
local instance1 = Instance.new("Part")
local instance2 = Instance.new("Part")

local a = InstanceHandle.new(instance1)
local b = InstanceHandle.new(instance1)
local c = InstanceHandle.new(instance2)

print(a == b) --> true
print(a == c) --> false

Equality depends on target identity, so it still works when the target isn't currently available.

Constructors 1#

newReturns a new InstanceHandle referring to the given Instance.

new(instance: Instance?)#

The handle refers to the instance weakly and doesn't extend its lifetime.

Luau
local target = Instance.new("Part")
target.Name = "TargetPart"

local handle = InstanceHandle.new(target)
local empty = InstanceHandle.new(nil)

print(handle:Get()) --> TargetPart
print(empty:Get()) --> nil

Throws if instance is neither an Instance nor nil.

NameTypeDefaultDescription
instanceInstance?The instance to refer to, or nil for an empty handle.

Methods 2#

GetReturns the referenced Instance if it's available locally, otherwise nil.
WaitYields until the referenced Instance is available locally, then returns it.

Get(): Instance?#

This method doesn't yield.

Get() returns nil when the handle is empty, when the target hasn't arrived on the client or server running the script, when the target is no longer available after streaming out, when the target has been garbage collected, and when the target isn't accessible to the calling script. Use InstanceHandle:Wait() to yield until the target arrives instead of checking once.

Returns
  • Instance? — The referenced instance, or nil if it isn't available locally.

Wait(timeout: number?): Instance?#

Returns nil if the handle is empty, the target is inaccessible to the calling script, or timeout elapses first. Wait() returns immediately when the target is already available and when the handle is empty.

Pass a timeout whenever you can't guarantee that the target reaches the caller. A target that's destroyed before it replicates leaves a handle that never resolves, and a Wait() with no timeout never returns. A pending wait can't be cancelled: task.cancel() stops your coroutine, but the wait isn't unregistered until the target arrives or the timeout elapses.

timeout must be a number greater than zero. Throws if timeout is zero, negative, or not a number.

NameTypeDefaultDescription
timeoutnumber?How long to wait, in seconds. Must be greater than zero. Waits indefinitely when omitted.
Returns
  • Instance? — The referenced instance, or nil if the handle is empty, the target is inaccessible to the calling script, or timeout elapses first.