Construct dynamic zones that utilise region checking, raycasting and the new BasePart.CanTouch property to effectively determine players and parts within their boundaries.
Ensure :getRandomPoint() returns nil instead of recurring infinitely if zone parts are 0, e.g. if all streamed all:
function Zone:getRandomPoint()
local region = self.exactRegion
local size = region.Size
local cframe = region.CFrame
local random = Random.new()
local randomCFrame
local success, touchingZoneParts
local pointIsWithinZone
local totalPartsInZone = #self.overlapParams.zonePartsWhitelist.FilterDescendantsInstances
if totalPartsInZone <= 0 then
-- Its important we return if there are no parts within the zone otherwise the checks below will recur infinitely.
-- This could occur for example if streaming is enabled and the zone's parts disappear on the client
return nil
end
repeat
randomCFrame = cframe * CFrame.new(random:NextNumber(-size.X/2,size.X/2), random:NextNumber(-size.Y/2,size.Y/2), random:NextNumber(-size.Z/2,size.Z/2))
success, touchingZoneParts = self:findPoint(randomCFrame)
if success then
pointIsWithinZone = true
end
until pointIsWithinZone
local randomVector = randomCFrame.Position
return randomVector, touchingZoneParts
end
line 87 of tracker so that it accounts for parts being streamed in:
local function playerAdded(player)
local function charAdded(character)
local function trackChar()
local hrp = character:WaitForChild("HumanoidRootPart", 0.1)
local humanoid = character:WaitForChild("Humanoid", 0.1)
local head = character:WaitForChild("Head", 0.1)
if hrp == nil or humanoid == nil or head == nil then
return
end
updatePlayerCharacters()
self:update()
for _, valueInstance in pairs(humanoid:GetChildren()) do
if valueInstance:IsA("NumberValue") then
valueInstance.Changed:Connect(function()
self:update()
end)
end
end
end
local hrp = character:FindFirstChild("HumanoidRootPart")
if hrp then
task.delay(0.1, trackChar)
else
character.ChildAdded:Connect(function(child)
if child.Name == "HumanoidRootPart" and child:IsA("BasePart") then
task.delay(0.1, trackChar)
end
end)
end
end
if player.Character then
charAdded(player.Character)
end
player.CharacterAdded:Connect(function(char)
charAdded(char)
end)
player.CharacterRemoving:Connect(function(removingCharacter)
self.exitDetections[removingCharacter] = nil
end)
end
Ensure
:getRandomPoint()
returns nil instead of recurring infinitely if zone parts are 0, e.g. if all streamed all:line 87 of tracker so that it accounts for parts being streamed in: