Area definition problem

Making a post because I’m honestly losing my mind at this point.

My question seems rather simple - how to define an area (i.e. location on the map) for later use.

The uses are:

  • To implement random encounter combat with varying enemy sets per location.
  • To change soundtrack according to the location player is currently in.
  • To possibly even announce which location the player enters (although I oppose the idea of gameplay where everything is laid in front of the player ready for grabs).

What approaches have I tried (and what didn’t work / I didn’t like implementation of):

  1. Making an invisible non-collidable brick conveniently named “EncounterArea” and using it’s Touched event.
  • First and the major part of my issue with this approach I ran into was that Touched only triggers once (or, more precisely, exactly 8 times, once per every object instance inside player’s character container) upon entering the area, and I would like the detection to repeat every once in a while until player exits said area so that repeatable random encounters are possible to implement at all.
  • Second and the minor part of the issue was that the brick, even when locked, retained it’s hitbox, which makes it tough to create / edit already created location on a whim. This, however, could be ignored and so I proceeded with trying to build upon this hacky solution.
  1. Using a timed while loop + WorldRoot:GetPartsInPart() for repeatable detection when triggering Touched event of “EncounterArea”.
  • This is where I disregarded going with both approaches - it just felt too inconvenient to code and integrate into my project. I didn’t have guts to embrace having to detect when player’s character touches a specific part instead of just entering something like Region3, and then having to make an ugly mess of a code chunk to check whether player was still in the area’s boundaries, AND THEN having to deal with latter’s very possible bugs and side effects.

I’m looking for everything between complete solution with code samples and absurd insights worded in gibberish with an indian tech guy sort of video attached to the comment.

I thank you for your time spent reading, comperhending and trying to help.

1 Like

i’m not sure waht you mean but if you need like things that is in a area you can do a loop and use region

I’m looking for some miraculous niche solution on how to detect stuff entering and being present in an area.

As for the Region3 - it’s deprecated.

Not sure if this is an answer but I’ll try.

TLDR check x and z is within the max-x, min-y, max-z and min-z

If you need to detect players or something with/close to the player then you can do a pretty active position check to say if x and z is within the boundaries of the areas in a local script then when it detects as in the areas a remote event tells the server to double check/verify that it’s in the area.
Then for other objects you just use a server script to check the positions (ofc only on objects that’s scripted to possibly ever move from one area to another) occasionally in a while loop

Example:

-- This constructs a zone based upon a group of parts in Workspace and listens for when a player enters and exits this group
-- There are also the ``zone.localPlayerEntered`` and ``zone.localPlayerExited`` events for when you wish to listen to only the local player on the client
local Zone = require(game:GetService("ReplicatedStorage").Zone)
local container = workspace.AModelOfPartsRepresentingTheZone
local zone = Zone.new(container)

zone.playerEntered:Connect(function(player)
    print(("%s entered the zone!"):format(player.Name))
end)

zone.playerExited:Connect(function(player)
    print(("%s exited the zone!"):format(player.Name))
end)
1 Like

Roblox broke developers’ best workaround for this. You used to be able to set the zone volume part’s to have some random CollisionGroupId and Studio’s dragger raycasts would ignore the part, so you could select anything else inside the bounds. Now, the best you can do as far as I know is to set the part to locked and hold down Alt to select things inside, just like you’d do for selecting parts inside a Model.

There are other solutions to your problem, but it depends a bit on what your zones look like. Firstly, are they 2D or 3D? In otherwords, can zone vary with Y coordinate, like if the second floor of a building has to be a different area from the first floor. Secondly, can the zones be described as regular shapes like rectangle or circle, or a group of these shapes together? Or, are the zones best described as complex polygons that would be cumbersome to fit a bunch of parts to? Next, how much does it matter that you detect the exact instant a player enters or leaves?

The last thing you might need to consider is whether or not zones need a dead band around them (or between adjacent zones) to prevent players from running along the boundary and repeatedly triggering enter and exit events.

One solution I’ve seen devs do, for the 2D case, is have zone parts below the world, and have the character periodically raycast straight down against just the zone parts. If the ray hits a part, the player is in that zone (all parts covering a zone are named with the zone name). You can put the zone parts inside Models like, so that a zone part moves around with a building. What you do is just tag the zone parts with CollectionService or with some naming convention, and when your server starts up, build a RaycastParams with an Include list that is only the zone parts, so that the raycasts can’t hit anything else. If your zone parts aren’t associate with other Models, just areas in a world, you can put them all in one Model to simplify the RaycastParams and not even need CollectionService.

1 Like

While having option to go 3D would be nice I don’t think it’s neccessary(at least not yet) because the only use for such zones I can think of are dungeon layers and I could implement this transistion by storing the current dungeon level elsewhere in the code.

Yes they can, I initially planned to use box-shaped parts for area definition purposes.

My two main purposes for having a defined zone are to initiate random encounters and change ambience, so while instant detection isn’t really important I would like the delay to be about 1 to 2 seconds or as much lower as possible without hurting perfomance.

I don’t think dead band is required because random encounter system(the way I see it) would work regardless and player ruining ambience of their own volition is not really my concern.

Major thanks for the advice, I will try tinkering with this solution in meantime, hopefully it works out.

Also, to clarify - I didn’t skip over this comment, but as a programmer I would like to firstly try to engineer a solution myself or at least implement something I understand the works of before pasting external modules into my projects.

1 Like

I forgot to mention one of the most simple solutions for the 2D case: a simple distance check. If you can approximate your zoned regions with circles, you can just use marker parts or attachments at the center of the regions, and check if the player is inside the radius of any of the circles that belong to each zone. It’s of course easy to put a deadband on these too, you just use 2 different radii that differ by at least the width of an avatar.

You can use CylinderHandleAdornments and BoxHandleAdornments to visualize regions without them eating mouse clicks and interfering with your building. Then, just delete them all at server startup.