ZonePlus v3.2.0 | Construct dynamic zones and effectively determine players and parts within their boundaries

After more tests it seems that the bug can be reproduced by merging an union/a part with a negative part and setting the collision fidelity to “Precise”, now the module will leave and enter multiple times if the player moves/jumps at some point

The module appears to be a bit buggy (works 50% of the time) when teleporting to a region about 20k studs away from the origin with streaming enabled opportunistic enabled. Used to works fine, but something went wrong after streamingenabled was modified and oppotunistic was enabled.

1 Like

Can you send a repo place file of this as I can’t reproduce this myself

I can’t seem to reproduce this, even when moving the test place over 100,000 studs from the origin and setting the following properties for Streaming enabled:

image

image

Are you ensuring the parts have streamed in before constructing the zones? e.g:

lightingAreas:WaitForChild("Green", math.huge)
lightingAreas:WaitForChild("Pink", math.huge)

I’ve updated the playground if you’d like to play around with this:
https://www.roblox.com/games/6166477769/ZonePlus-Playground

@ForeverHD
Found a weird bug with having .playerEntered on the client. I’ve provided a video and the code used.

Basically, the zone doesn’t detect a player ( if that 1 player has died ), both players have to die in order for it to be accurately detected once again.

Zone.playerEntered:Connect(function(Player)
     print(Player)
end)

edit : the bug can not be replicated inside of roblox studio, only happens in game.

1 Like

Thanks for your report! I’ve done some digging and it appears there were some cases with streaming which ZonePlus wasn’t accounting for. Updating the function on line 87 of the Tracker module to the following should fix this:

image

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

I’ll deploy this change officially at a later date alongside a group of other updates.

5 Likes

My experiences were teleporting to the area instead of moving to it though, but let me try to send you something

Thanks, this solution works perfectly!

Hello
Where can I find some examples about the settings group names, which can be used in zone:bindToGroup?

I found example of using zone:bindToGroup(“EnterOnlyOneZoneAtATime”)
but what is the exact effect of this?
what are the other possible Groups? Are these pre-defined or I have to define them?

Thank you

Hi, you can find more details here and here:

The settingsGroupName doesn’t impact its properties directly, you could name the group "RedZones" for example for the exact same effect.

When calling bindToGroup, if the settingsGroupName hasn’t been created before it automatically creates it internally for you. There’s only one property right now, onlyEnterOnceExitedAll , which defaults to true.

We’ve designed it this way in case we wish to add additional properties in the future.

1 Like

Hi ForeverHD! I am a big fan! Ok Sorry that’s off topic.

1 Like

ok, so I do not need to define any groups in advance.
Once I use zone:bindToGroup, I automatically get the behaviour - onlyEnterOnceExitedAll=true, no matter what group name I use?

1 Like

That’s all correct yep, you get the default behaviour (i.e. onlyEnterOnceExitedAll=true) no matter what name you use :+1:

2 Likes

Thank you
I am going to use the zones (inside a LocalScript) to change the ambient sound when the player walks in a different part of the map. I am going to put a zone at the “door” between the zones, which will trigger the change of the sound when the player passes through it.
I see that there is a possibility to set the Accuracy of the zone. I wondered whether I should use Medium, because the change of sound is not that critical if it happens with a little delay.
However if the player travels through the border zone faster than 0.5 sec. is it possible that the zone event never triggers?
If such thing is possible, then I probably will leave it by default to High accuracy (10 checks per second). Performance wise is this still better compared to using the Touched event in the LocalScript?

1 Like

Yes it’s typically best to avoid touched events for reasons mentioned in these threads:

ZonePlus utilises whitelists and spatial queries which have been highly optimised internally by Roblox. If you’re using localPlayer events you’ll be absolutely fine with any Accuracy, including ‘Precise’.

If you used a low accuracy and ran through a narrow zone then yes it is possible that the item or player is not detected at all.

4 Likes

Hello, I don’t know know if this has already been answered, but I am wondering if there is a way that I can get the name of the individual zone that the player has entered?

Example:

zone = Zone.new(FolderWithMultipleParts)

The Folder with multiple parts has 5 zones named zone1, zone2, zone3, zone4, zone5 respectfully.
So these 5 individual zones are parts in the folder: FolderWithMultipleParts

When I enter one of the zones is there a way that I can access zone3 for example from the function

zone.playerEntered:Connect(function(player)
– Access the specific zone here?
end

Are there any functions I can call that can achieve this?

I tried running a loop through the zones folder and calling zone:findPart(), but it returned all the zones instead of the one zone that my player had entered.

Any advice/guidance would be very appreciated.

Thank you!

You can use a dictionary table to achieve this:

local zonesDictionary = {}
for _, container in pairs(folderWithMultipleParts) do
   local zone = Zone.new(container)
   zonesDictionary[container.Name] = zone
end

local zone1 = zonesDictionary.zone1
local zone2 = zonesDictionary.zone2
etc
2 Likes

I have this issue where I teleport the player inside the zone and it doesn’t register as the player being inside the zone when I use findPlayer()

(It returns false even though I’m inside the zone)

Can you share a roblox place file of this please so I can take a look

2 Likes

I log in and out, it works fine but when I reset and go back to the zone, the script seems to stop working. I don’t know if there is something missing in the script to make it work.

local ZoneModule = require(game.ReplicatedStorage.Zone)
local Zone = ZoneModule.new(workspace.Zone1)
local Update = Zone.autoUpdate --[default: "true"]

local color = workspace.Zone1["Body Colors"]


Zone.localPlayerEntered:Connect(function(player)
	print(player.name.. " AMPUTAR")
	local char = player.Character or player.CharacterAdded:Wait()
	local clone = color:Clone()
	clone.Parent = char
end)

Zone.localPlayerExited:Connect(function(plr)
	print(plr.name.. " AMPUTAR mas saiu do lugar")
	local paint = "Body Colors"
	local char = plr.Character
	local clone = color:Clone()
	clone.Parent = char
end)