@Abbaok_origin I’ve added in a Zone:getRandomPoint() which returns a random balanced CFrame within the zone. The zone achieves this by creating ‘clusters’ and setting up ‘weights’ based upon a clusters volume. I’ve decided not to introduce an ‘inner boundary’ method as this would require duplicating a lot of methods and properties. I recommend setting up a secondary zone to achieve your desired effect:
I’ve also setup a ‘Coin Spwner’ example:
You’re now welcome to require the MainModule for automatic updates.
@TheRings0fSaturn I’ve modified the core code so you can achieve this effect. The default additionalHeight is now 0, so you don’t even have to specify this parameter when constructing future zones:
I’ve also introduced a ZoneService for easy management of zones between modules and scripts.
Feel free to check out the ‘Theory’ section at the top of the post for an explanation on why it uses regions and raycasting.
Events can be as intensive (precise) or light as you decide. The playerAdded and playerRemoving events require :getPlayers() to be called at frequent intervals, or :initLoop() once (which calls this repeatedly). The docs explain this further here:
I think I have a problem for this, the problem is if the player leaves the region3 his vote is not stored but using .Touched events like in my voting system this isn’t a problem. For example player A steps on pad then he goes to padb then he decides to go away his vote doesnt store. Is there a way to eliminate this so I can start using the region3 method. Currently I use .Touched for my voting module with for i,v in pairs
Edit: Unless if your doing a while true do loop with region3, but isn’t that more performance heavy then events?
Also for voting pad’s there aren’t really complex shapes so in my case which one would you choose, for voting system and can you also explain the above to
Dang… I saw the coin demo and thought all my problems will be solved Unfortunately, no… my problem is, when player gets killed in my game, he’s supposed to drop the item he had, but I need to know weather it’s intersecting with other parts, and if so, find the optimal path to take, to un-stick itself, so it never gets lost in buildings. I thought i could use this to find how it’s intersecting, so i can move it accordingly (i guess i could make it physics object…)… Still a really useful tool for future!
The zones are removed after voting has completed in the example I provided, so you’ll want to create an additional table of information independent of Zone+ to store any further data you need. Using Region3 over .Touched events, and vice versa, shouldn’t impact your ability to store information - can you expand on this?
Touched and Untouched events are typically fine for ‘activations’, such as collecting a coin, however not so much for ‘entering and leaving’ as these events are often unpredictable (untouched often fires before touched, untouched sometimes never fires at all when leaving a part, etc). That’s the primary use behind using region3 and raycasting: reliable data.
In terms of performance: .Touched and .Untouched events are fired every single time an object moves within the part (i.e. 60 frames per second), which becomes performance heavy with multiple complex shapes. In contrast, Zone+ initLoop defaults to 2 ‘checks’ per second (10 in the voting example for more precision), using raycasting and regions which are well optimised internally by Roblox.
:getRandomPoint() returns the randomly generated CFrame value within the zone, along with the ‘zone part’ directly below it, and the intersection vector between this random point and ‘zone part’, which may help you out.
You could also try Thomas/Evaera’s implementation of GetTouchingParts independently of Zone+ which may help you solve this:
If you’re using the zones playerAdded and playerRemoving events, and have called Zone:initLoop(), then the zone will repeatedly call :getPlayers() (i.e. perform region and raycast checks) in a loop.
The object compares the previous players within the zone against the new ones, and determines when a player enters and leaves based upon this, which is why it’s necessary to call getPlayers() at frequent intervals - the more intervals, the greater the precision, the greater the cost.
Loops aren’t inherently evil if used appropriately. In this scenario they’re fine as region and raycast checks are well optimised internally, and are only being performed a few times a second.
For the voting pads example, the loop is only necessary for the duration of the ‘voting’ period, therefore can be ended as soon as it’s complete.
I’ve just deployed a fix for this, thanks for the report! Originally what was happening: when instances from the zone group were destroyed right before the zone being removed, the ‘a part had changed in the group’ event was fired, added to the update queue, then Zone:update() called 0.1 seconds later, only for the zone properties (like signals) to not exist. To prevent this, I now have the auto-updater check the zone is still active before calling this method.
Does this module have some sort of priority system?
Example: I set Zone B’s priority to 2, and I set Zone A’s priority to 1.
The player is inside Zone B, but also Zone A. If I use the getPlayersInRegion method on Zone A, it wouldn’t return any players. But if I used it on Zone B it’d return the player. It’s kind of hard to explain but I hope you understand what i’m trying to say.
I am looking at the Documentation in the original post but I can’t seem to understand which way I am supposed to do in order to create multiple separate zones. Should I be using ZoneService:createZone() or Zone.new() multiple times?
@AspectW This isn’t directly supported by Zone+, however you can easily achieve this effect by returning a list of players within both regions (using getPlayersInRegion as you mentioned), then making the necessary weight and player comparisons.
@AbandonedRick Both methods create and return a Zone object (createZone calls Zone.new() internally); you can use either to create multiples zones.
If you’re creating zones which don’t need to be referenced from an outside source (e.g. another script), you can simply use local zone = Zone.new(group) to create the zone, then call zone:destroy() to remove it.
Likewise, if you plan on referencing a zone from an outside source, you can do ZoneService:createZone("ZoneName", group) to create the zone, ZoneService:getZone("ZoneName") to retrieve it, and ZoneService:removeZone("ZoneName") to remove it.
Some background before the question, basically I’m trying to create two different zones, and call :initLoop() on the zones at different times depending on the status of Lighting service’s ClockTime. I’m trying to call :endLoop() before initializing the alternative zone but for some reason it’s not switching loops. However the first zone’s events are connected and looping.
If you could please take the time to see how I’ve set this up and maybe guide me in the right direction, I’d really appreciate it.
Regarding output, the prints within the while loop initially prints 1 once then prints 2 whilst it is not cell time, when it is cell time it then prints 6 once then continues printing 5, however the events for the second zone are not looping.
EDIT: I also tried creating 2 zones in 2 different scripts and controlling it that way, still doesn’t seem to work, :endLoop() stops the events from running and :initLoop() doesn’t start the loop for the opposing zone. Here are the pastebin’s for each zone: