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

Just came back to delete my post cause I just had that fix/idea. I feel very stupid lol. This might be the best resource to ever cross me on the forums. Wow you sir, are a legend.

2 Likes

How would you go about spawning a NPC with the custom scaling (BodyHeightScale, BodyWidthScale, etc) in a zone using the coin spawner example as a basis? I got the spawning of an NPC to work at a normal height (using R15) where using local distance = 3 would have feet flat on the floor.
Whenever changing the scale of the bases, to a random number between 0.65 and 0.9, the NPC would float. I’ve tried multiplying the distance = 3 by the scale as well as multiplying the CFrame from intersectionvalue by a CFrame with the scale and it still floats.
I’m aware this is more of a question for the code help category, but considering it’s a ZonePlus related thing figured I’d try here. If I need to move it let me know.

1 Like

Hello! Just stumbled upon this system and was wondering, how efficient is this system? Currently for my game what I do is (and this may be a little weird at first) is I create a region 3 around the player, a box of some sort, and have invisible parts (usually 1x1x1 and transparent/anchored/non-can collide) placed within a folder that I whitelist for the region 3 checks.

Additionally, I can create separate folder parents for organization or place an ObjectValue for further classification of what kind of region I am in. This generally results in O(1) in terms Big O algorithm complexity since I am having the do the same region3 checks no matter how many regions I decide to add into my game.

I am wondering if this system is any more efficient than my own and whether I should switch to it or not. Thanks again for this amazing opens source stuff @ForeverHD , always loved your work!

1 Like

A neat trick for calculating the height of a default character is by multiplying it’s HumanoidRootPart Y size by 2 then adding on the head Y size (since the legs are always the same size of the HRP). You can then extend this method to obtain the entire square volume of a character (the arms are always HRP X size divided by 2) and best of all it works with both R6 and R15.

2 Likes

WOW this pack looks great :star_struck:!
try adding a low gravity zone in the next update!

1 Like

Hi there, I’d highly recommend checking out the methodology page which explains all of this in detail:

In short, ZonePlus is dynamic therefore the methods vary depending upon the events you use and other factors such as the total volume of characters, parts and zones.

In short, the player-detection method (when the total volume of zones exceeds the total volume of characters) sounds similar-ish to yours, except it utilises EgoMoose’s RotatedRegion3 module with whitelists.

Zones are also abstracted to appear as singular entities (for ease of use) however behind the scenes act as a collective for optimisation reasons (i.e. they share data instead of generating it individually).

We’re also exploring new optimisations mentioned here - when ‘Detection’ is set to ‘Automatic’ ZonePlus will dynamically adapt the size of these region checks (i.e. striking a balance between accuracy and performance) to allow for hundreds of players in a server with negligible effect on performance.

1 Like

Amazing! Keep on doing the amazing work you are doing!

Ah, alright! So it seems like you have a Rotated Region3 the size of the player’s character on the LocalPlayer implementation and use the zones as whitelists to check if the player is within them? Sounds neat! Is the Rotated Region3 module by EgoMoose any more efficient than the Roblox implementation of Region3’s or is the reasoning behind your usecase due to it supporting rotated Regions?

And looking at the documentation, if I disconnect the events, the checks no longer work correct? That’s much neater than what I had implemented considering the checks don’t do any extraneous work other than checking the players region.

Again, thank you!

Roblox regions don’t account for rotation or special shapes like wedges. EgoMoose’s RotatedRegion3 uses clever math and is built ontop of roblox’s Region3 methods to account for rotated parts and different part types.

Correct yep, when all zone connections (like that returned from .playerEntered) are disconnected, or if the zones are destroyed (zone:destroy()) then checks will cease.

Really nice module, worked perfectly to create a system to generate parts over a dynamic terrain. Good job! :grinning_face_with_smiling_eyes:

We’ve been using this for a server with up to 80-100 players
with a total of 34 zones.

Only downsides I’ve been seeing is that we have one tool relying on mouse.Target which keeps picking up the ZonePart because I thought I could just keep ZoneParts inside ServerStorage, but they actually need to be in Workspace. We simply just made the ZoneParts nearly the exact size as the roof all the way around so the player’s camera is always in the Zone.

I’ll be looking into this once you release Detection options! I just need to know if a player is in or not, not limbs etc.

I’ll be up for testing any performance gains!

1 Like

Thanks, it took a few days but I eventually got it. That led me in the right direction.

1 Like

Hey There! Was just doing a look through before implementing and I came across this snippet of code within the ZonePlus V2 main module. It was using a wait function within a coroutine. Correct me if I’m wrong, but I’ve observed that threads containing a wait function get resumed through the same WaitingScriptJob task scheduler that handles functions such as spawn, wait, and delay, which is prone to budgeting. This could lead to unexpected behavior in case the person using this module also happens to use these function extensively elsewhere.

Anyway, just thought it was worth mentioning, here is a snap shot of where I found this. I replaced it with a quick while yielding operation for the same time as written within the module. Again, thanks for the module though, everything else seems great!

Snap Shot
RobloxStudioBeta_Rs9LjuHZx1

1 Like

Good spot thanks, we use heartbeat connections and clock checks for the important zone detection and must have missed that off for the updater (which is rarely used). I’ll open up an issue for this and have it fixed for v2.1.0

I was wondering whether teleporting a part that has entered the zone to a position outside the zone is supposed to break the behaviour of the partEntered functionality. Currently I’m facing this issue. It fixes itself when the same part enters the zone again and exits out of it.

Does the exit function need to fire for the enter function to work again?
If so is there a way I can manually do that to make the enter function work again?

1 Like

Assuming a part is already in a zone then yes, it would have to exit the zone before the entered event can be fired again. I can’t see how this would be a problem though?

If you are teleporting a part outside the zone and the exited event didn’t fire then that would be a bug. Could you explain what you’re trying to do in more detail?

Also note that part events only work for unanchored parts.

2 Likes

Thanks for the response. What I originally tried to do was to teleport the part that entered the zone to a specific position. So the code would’ve looked like this:

-- "Part" is a ball and un anchored when entering the zone

-- zone.partEntered() event fires
Part.Anchored = true
Part.Position = Vector3.new()
Part.AssemblyLinearVelocity = Vector3.new()
wait(1)
Part.Anchored = false

As you mentioned, the problem seems to be with the anchored part. I didn’t know about this before. I have now modified my script to work accordingly with this behaviour in mind and is working properly. Thanks

2 Likes

No problem, I don’t think I mentioned this in the docs so I’ll add a notice to make this clear

1 Like

You can set a name property to achieve this or user zone.groupParts, explained in more detail here:

In short, if your zone contains multiple parts and you want to retrieve an individual parts name from that zone when you enter it, you should instead split these parts up into their own zones each, then set a name or instance property for each and check for this.

There’s no change to performance when you split up zones so this is the best solution. For example, 1000 zones of total volume 500 studs squared is equivalent in performance to 1 zone of volume 500 studs squared (for the player events at least).

1 Like

Is it possible to do zone.new() without using parts, maybe create a zone using positions?