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

Why are you zoning one part in a small size like that…? Just use .Touched instead if you’re just gonna do that.


I’m having an issue with zones not recognizing a player leaves a zone on death or when the character is reset. If they reset their character or die in a zone and immediately respawn in the zone, the zone sees as they never left the zone. I currently have a safe zone implemented where I give a forcefield to players when they enter a safe zone. If they reset their character and respawn immediately in the zone, they won’t get the forcefield again. Is there any way to make sure the playerExited is called when the character is reset or is dead?

I fixed the issue. I had multiple parts parented to one, I’ll just use a folder

Good call, this appears to occur when a player dies within a zone then immediately respawns within that zone. The time difference is so minimal zoneplus then doesn’t detect that player leaving (therefore the new character entering also doesn’t trigger).

This is a logic error on our end so I’ll write up a fix shortly and hopefully have it deployed today or tomorrow.

If this is on the client, try zone:setAccuracy("Precise").

Is this a bug? When I join the game, destroy character model, and replace it with a new one, Zone+ doesn’t work at all. Will there be a fix for this?

ZonePlus will certainly require a player.Character in order to function (for the player related methods and events at least).

What errors are produced?

There were no errors when I tried touching the part.

Can you provide or DM me an uncopylocked stripped-down place and/or details which reproduces this. Doing game.Players.ForeverHD.Character = workspace.Guest666NPC appears to work perfectly fine for example on the server.

@davidsochill @0msh @Alvin_Blox

This should be fixed now in v2.1.2:


Is there any way we’re able to get all the part’s parents with :getParts()?

And with :getParts(), are we able to filter out which parts it detects?
Like if there’s a part titled Basepart, and I want only it to be returned, and not anything else touching in the zone, is that possible?

Just filter the results from the returned table. There would only be negligible improvement in performance if we supported this internally for the whitelists. For instance:

local partParents = {}
local parts = zone:getParts()
for _, part in pairs(parts) do
    local parentPart = part.Parent
    if part.Parent:IsA("BasePart") then
        table.insert(partParents, parentPart)

Then repeat a similar method for rotated parts, etc.

Hey there, is there a way to get a zone from a different script? Or atleast-- the server is able to check if a player is inside a zone. I am trying to make a region verification (see if player is actually inside a zone).

My main concern is not with the local detection itself; it’s the firing of RemoteEvents.


local ZoneModule = require(replicatedStorage.Zone)
local RemoteEvent = replicatedStorage.RemoteEvent

local zone =

What the ServerScript would look like:

local ZoneModule = require(replicatedStorage.Zone)
local RemoteEvent = replicatedStorage.RemoteEvent

   -- how do I verify that the player is inside the zone (server-sided?) and it's not just an exploiter firing the remote?

I have tried passing through the “zone” table in the events, but obviously it wouldn’t work.
Yes, there is a specific reason why I’m using localPlayerEntered and not PlayerEntered via the server.

Any help is appreciated, thanks so much!

zone:findPlayer(player) should do the trick:

   local inZone = zone:findPlayer(player)
   if inZone then
      -- verified, do your stuff
1 Like

That’s the thing, “zone” would be undefined. I can’t pass it through the remotes either.

unless doing local zone = in the serverscript wouldn’t create a separate “zone” and it’ll just grab the existing one.

As ZonePlus doesn’t involve networking you’d need to independently setup a zone on both client and server. These zones would be constructed from the same parts/groups and would require a separate name to identify them which is then passed through the remotes.

For instance:

  1. Construct zones on the server, all of unique names, then store these in a dictionary, with a name-zone pair for its key and value.

  2. Repeat the same on the client

  3. Client makes a request to the server, passing through the zone name it states to be within

  4. Server receives request, performs sanity checks (e.g. caps the number of these requests to 2 per second)

  5. If server check approved, index the dictionary for the corresponding name. If present, perform the findPlayer check.

  6. Do your stuff with those results

You may also find ZoneController:getTouchingZonesArray(player) useful:

1 Like

first of THANK YOU @ForeverHD for this amazing module, I have been using it since v1 and this new v2 is EVEN BETTER!

I notice the documentation says:

  • Infinite zone volume, zero change in performance - zones can now be as large as you like with no additional impact to performance assuming characters/parts entering the zone remain their normal size or relatively small

This is great! I have some very large zones and i just want to clarify that zones can be infinite volume and can also be made up of many parts without a performance hit. I am using perhaps 30-40 parts to get the shape i need, will this be ok?

Correct and that’s fine. With v2 your zones can be as large and contain as many parts as you like with negligible increases to performance (when number of players remains constant) due to dynamic character checking, explained here:

1 Like

Hello! I’m having a little bit of an issue with this. It’s my first time using region3 so it’s possible I have done something wrong, but here is my code so far:

-- I placed the module in server script service
local mod = require(game.ServerScriptService.Zone)

-- This script is inside a part by the way (Server script, not local)
local zone =

        print("Player entrered")

For some reason, the print doesn’t show up even when I step on the part. Do you know why? Thank you so much for this module!

Your code is perfectly fine:

Can you share more details on the setup, such as a snapshot of the script.Parent in workspace, an image of the part itself, and details of the parts properties?