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.
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)
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.
Declare the region part + size + CFrame
Create a Region3 object using the properties from 1. (uses some math)
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 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
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
EDIT: Had to change inequalities to fit function name (point inside region returns false)