What is the quickest and most efficient way to check if a player is within a region?

I have this safety zone in which players cannot be damaged. I will simply hook up all damage events to check if the damaging player is NOT within the safety zone. I used a block part to illustrate the zone:


Players will constantly be checked if they are within this region as players outside the region can initiate the damage event so efficiency and speed as well as performance is quite important. I have a few ideas in order to achieve this.

Idea 1: Using :FindPartsInRegion3 to check if the player is not within a region. However, this method I hear is not efficient as it has to loop through every single part in that region, plus it does not support regions that are diagonal.

Idea 2: Using magnitude to check if players are within a certain distance, however, this results in the safety zone being spherical rather than an illustrated block.

Idea 3: Using touched/touch ended events to insert players into an array, then simply check if they are in a safety table. However, knowing Roblox physics, this is not reliable.

Idea 4: Using some kind of CFrame maths and points, however I am not too strong on this whole CFrame maths thing and for all I know this could be inefficient and performance taxing.

Could someone possibly guide me on this? Thanks.

3 Likes

Check if the player who wants to damage anything is within the 8 vertices of the “safe zone”

Would be your best bet…

1 Like

I believe that both EgoMoose and AxisAngle have released region3 modules that support rotations. You can find EgoMoose’s here. However, I’ve had decent results using GetTouchingParts.

2 Likes

I have a system that determines this very well! I used it to determine if a player was on a map, it should be very accurate, and fast enough that it’s safe to do it at 60 FPS (I do this in my games, had no lag issues)

1 Like

Hi I found an answer that answered a similar question a while back. I couldn’t find it but I had the code so I modified it. It uses your last idea (and what GreekForge said) but shouldn’t be too bad on performance.

Guide:

  1. Declare the region part + size + CFrame
  2. Create a Region3 object using the properties from 1. (uses some math)
  3. Create a function canDamage(plrPos) that checks if a point is in a region.

To complete 3. you need to get the distance “D” from the centre and the point in question “P”. Dividing this by the size of the object will scale your “D” such that one unit in each x,y,z is the size of the regions x,y,z. You can then do some simple inequalities that check if your “D” is outside (or within) the 1 unit range (remember from the centre its half the distance).

If you want the explicit code I’ve put it down underneath.

-- Declare the region part
local part
local size = part.Size
local partCFrame = part.CFrame

-- Create region
local max = partCFrame.p + (0.5 * size) -- imagine this as the top right corner
local min = partCFrame.p - (0.5 * size) -- this is the opposite corner
local region = Region3.new(min, max)

local function canDamage(playerPosition)
    local point = playerPosition 
    local relativePosition = (point - region.CFrame.p) / region.Size
    
    --//Check Bounds
    local inRegion = -0.5 <= relativePosition.X and relativePosition.X <= 0.5
        and -0.5 <= relativePosition.Y and relativePosition.Y <= 0.5
        and -0.5 <= relativePosition.Z and relativePosition.Z <= 0.5
    
    return not inRegion
end

EDIT: Had to change inequalities to fit function name (point inside region returns false)

16 Likes