Skip to content

Fix disconnectObserverFromGroup using wrong lookup table#17

Merged
LDGerrits merged 1 commit intoLDGerrits:mainfrom
C6H15:fix/observer-disconnect-wrong-table
Apr 9, 2026
Merged

Fix disconnectObserverFromGroup using wrong lookup table#17
LDGerrits merged 1 commit intoLDGerrits:mainfrom
C6H15:fix/observer-disconnect-wrong-table

Conversation

@C6H15
Copy link
Copy Markdown
Contributor

@C6H15 C6H15 commented Apr 9, 2026

In the prior fix State.entityToObservers was used and observer IDs matched against group IDs. This could skip exit callbacks when unsubscribing an observer from a group. The fix is to iterate through State.entityToGroups instead.

Test (Server)
--!strict
local QuickZone = require(workspace.QuickZone)

local Red = Color3.fromRGB(255, 0, 0)
local Blue = Color3.fromRGB(0, 0, 255)

local ZonePart = Instance.new("Part")
ZonePart.Anchored = true
ZonePart.CastShadow = false
ZonePart.CanCollide = false
ZonePart.Name = "Test"
ZonePart.Position = vector.zero
ZonePart.Size = vector.one * 20
ZonePart.Material = Enum.Material.ForceField
ZonePart.Color = Color3.fromRGB(0, 0, 255)
ZonePart.Parent = workspace

local function CreatePart(Color: Color3, Angle: number): BasePart
   local Part = Instance.new("Part")
   Part.Anchored = true
   Part.CastShadow = false
   Part.CanCollide = false
   Part.Position = vector.create(math.cos(Angle) * 5, 3, math.sin(Angle) * 5)
   Part.Size = vector.one * 2.5
   Part.Material = Enum.Material.SmoothPlastic
   Part.Color = Color
   Part.Parent = workspace
   return Part
end

local RedParts = {
   CreatePart(Red, 0),
   CreatePart(Red, math.rad(120)),
   CreatePart(Red, math.rad(240)),
}
local BlueParts = {
   CreatePart(Blue, math.rad(60)),
   CreatePart(Blue, math.rad(180)),
   CreatePart(Blue, math.rad(300)),
}

local Zone = QuickZone.Zone.fromPart(ZonePart)
local RedGroup = QuickZone.Group.new({
   ["entities"] = RedParts,
})
local BlueGroup = QuickZone.Group.new({
   ["entities"] = BlueParts,
})
local Observer = QuickZone.Observer.new({
   ["groups"] = {RedGroup, BlueGroup},
   ["zones"] = {Zone},
})

Observer:onEnter(function(Entity, Zone)
   if Entity:FindFirstChildOfClass("Highlight") == nil then
   	local Highlight = Instance.new("Highlight")
   	Highlight.FillTransparency = 0.75
   	Highlight.DepthMode = Enum.HighlightDepthMode.Occluded
   	Highlight.FillColor = Color3.fromRGB(0, 255, 0)
   	Highlight.Parent = Entity
   end
end)

Observer:onExit(function(Entity, Zone)
   local Highlight = Entity:FindFirstChildOfClass("Highlight")
   if Highlight ~= nil then Highlight:Destroy() end
end)

task.delay(5, function()
   local Count: number = 0
   Observer:unsubscribe(BlueGroup)
   for _, v in BlueParts do
   	if v:FindFirstChildOfClass("Highlight") == nil then continue end
   	Count += 1
   end
   if Count > 0 then
   	print(`Only {Count}/{#BlueParts} blue parts still have highlights after unsubscribing.`)
   else
   	print(`All highlights have been removed.`)
   end
end)

In the prior fix `State.entityToObservers` was used and observer IDs matched against group IDs. This could skip exit callbacks when unsubscribing an observer from a group. The fix is to iterate through `State.entityToGroups` instead.
@LDGerrits LDGerrits merged commit d282424 into LDGerrits:main Apr 9, 2026
@C6H15 C6H15 deleted the fix/observer-disconnect-wrong-table branch April 9, 2026 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants