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:
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
endPrefer 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:
local part = Instance.new("Part")
print(part:GetAttribute("Target")) --> nil
part:SetAttribute("Target", InstanceHandle.new(nil))
local handle = part:GetAttribute("Target")
print(handle:Get()) --> nilInstanceHandle 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():
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:
local function sendHandle(remoteEvent: RemoteEvent, player: Player, spawnedModel: Model)
local handle = InstanceHandle.new(spawnedModel)
remoteEvent:FireClient(player, handle)
endIn a client script, call this function with the same remote event to start listening before the server sends the handle:
local function receiveHandles(remoteEvent: RemoteEvent)
remoteEvent.OnClientEvent:Connect(function(handle)
local model = handle:Wait(10)
if model then
print("Received", model.Name)
end
end)
endOwnership#
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.
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) --> falseEquality depends on target identity, so it still works when the target isn't currently available.
Constructors 1#
| new | Returns a new InstanceHandle referring to the given
Instance. |
new(instance: Instance?)#
The handle refers to the instance weakly and doesn't extend its lifetime.
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()) --> nilThrows if instance is neither an Instance nor nil.
| Name | Type | Default | Description |
|---|---|---|---|
instance | Instance? | The instance to refer to, or nil for an empty handle. |
Methods 2#
| Get | Returns the referenced Instance if it's available locally,
otherwise nil. |
| Wait | Yields 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, ornilif 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.
| Name | Type | Default | Description |
|---|---|---|---|
timeout | number? | How long to wait, in seconds. Must be greater than zero. Waits indefinitely when omitted. |
Returns
Instance?— The referenced instance, ornilif the handle is empty, the target is inaccessible to the calling script, ortimeoutelapses first.