← resources/ module / zone-detect
FREE
Zone detection (spatial-query)
Reliable zone enter/leave using GetPartBoundsInBox on Heartbeat — no more players skipping through thin .Touched zones at speed.
ZoneDetect.luaupreview — first 10 of 61 lines
--!strict-- ZoneDetect — reliable zone enter/leave without .Touched.-- Polls GetPartBoundsInBox on Heartbeat so fast movers are never missed.local RunService = game:GetService("RunService")local ZoneDetect = {}ZoneDetect.__index = ZoneDetectexport type Zone = { part: BasePart, inside: { [BasePart]: true }, entered: RBXScriptSignal, left: RBXScriptSignal,}function ZoneDetect.new(part: BasePart) local self = setmetatable({}, ZoneDetect) self.part = part self.inside = {} self._entered = Instance.new("BindableEvent") self._left = Instance.new("BindableEvent") self.entered = self._entered.Event self.left = self._left.Event self._conn = RunService.Heartbeat:Connect(function() self:_step() end) return selfendfunction ZoneDetect:_step() local params = OverlapParams.new() params.FilterType = Enum.RaycastFilterType.Exclude params.FilterDescendantsInstances = { self.part } local hits = workspace:GetPartBoundsInBox(self.part.CFrame, self.part.Size, params) local seen: { [BasePart]: true } = {} for _, part in hits do seen[part] = true if not self.inside[part] then self.inside[part] = true self._entered:Fire(part) end end for part in self.inside do if not seen[part] then self.inside[part] = nil self._left:Fire(part) end endendfunction ZoneDetect:destroy() self._conn:Disconnect() self._entered:Destroy() self._left:Destroy()endreturn ZoneDetect