GetInstanceAddedSignal can cause all Connects to occur twice if associated Objects parent is nil and SignalBehaviour is Immediate

Immediate mode signal behaviour seems to have an issue where connecting signals occur twice.
This only happens when an GetInstanceAddedSignal calls an object that was immediately created and not yet parented to the workspace; then all Connects inside that related function seem to occur twice.

Here’s a simple example to paint a picture:

Put 2 objects in storage and have one with a click detector
Have your second object contain a click detector.

game.CollectionService:GetInstanceAddedSignal("MyTag"):Connect(function(object)
	local second = game.ReplicatedStorage.second:Clone()
	second.ClickDetector.MouseClick:Connect(function()
		warn("TestMessage")
	end)
	second.Parent = object
end)

local first = game.ReplicatedStorage.first:Clone()
first:AddTag("MyTag")
first.Parent = workspace

If you attempt to click the newly spawned big object in your scene, the event will trigger twice and you’ll see 2 prints in the output.

This issue only occurs if your SignalBehaviour is set to Immediate, part of the new changes from here:

Workarounds:

  • Add the tag after the object has been parented to workspace
  • have a yield of some kind inside GetInstanceAddedSignal (task.wait, task.delay)

Addendum:

  • task.spawn inside the GetInstanceAddedSignal doesn’t solve the issue
  • I have only tested so many signal connect calls inside this function for test purposes, I’m not entirely sure if this goes for every signal connect, but I’m willing to be it’s true based on what I’ve seen so far

Repro Place for convenience: (click red block in scene)
ConnectTwice.rbxl (54.1 KB)

2 Likes

I’ve shortened and updated the reply (based on further tests and what aaron_mccoy pointed out - thanks!).


Upon further investigation we’ve come closer to narrowing the issue span down to some of the instances that work with user input, namely ClickDetectors, DragDetectors, ProximityPrompts, and maybe a few more, not including guis with buttons.

GetInstanceAddedSignal() listener fires a single time, yet the specific signals associated with user interaction are received twice. Examples of events affected by the issue are MouseClick, MouseHoverEnter and DragStart.

On the contrary, other signals are received as expected. Any value instance events, attribute events, bindable events, and most other instances are not impacted by the issue, and neither are inherited events of affected instances, which are not associated with user input (such as Changed).

It doesn’t matter when the event is connected as long as it was part of object B before it was parented to object A (with a tag). Parenting to workspace, parenting outside the callback, or parenting object A before adding the tag renders expected results.

Repro (another variant)
local blue = Instance.new("Part")
blue.Name = "Blue"
blue.BrickColor = BrickColor.new("Deep blue")
blue.CFrame = CFrame.new(0,.5,-5)

local red = Instance.new("Part")
red.Name = "Red"
red.BrickColor = BrickColor.new("Really red")
red.CFrame = CFrame.new(0,1.5,-5)

local clickDetector = Instance.new("ClickDetector", red)

game.CollectionService:GetInstanceAddedSignal("Tag"):Connect(function(instance)
	print(instance.Name.." added")
	red.Parent = blue
end)

blue:AddTag("Tag")
blue.Parent = workspace
--red.Parent = blue
--red.Parent = workspace
task.wait(1)
--local clickDetector = Instance.new("ClickDetector", red)
clickDetector.MouseClick:Connect(function() print("Clicked") end)

The issue occurs with proximityprompts as well

2 Likes

What’s wrong with adding the tag AFTER parenting it to workspace?

1 Like

There’s nothing wrong, but this is a very contained example. There’s people out there, including me, who already have very complicated codebase setups, and not knowing that this is a root cause of their Signals being connected twice can cause them a lot of heartache.

So ideally this issue just never happens and either usecase is acceptable

Time is a debounce and cannot have an exact typology. The engine cannot recreate time in such a matter that it is the same in the real world. The only solution to this is the magnitude and how you exploit it.

Thanks for the report! We’ll follow up when we have an update for you.