I know there’s a way to do this,
I have made parts and used the Touched event but that doesn’t work because when I player equips a tool it says that the player TouchEnded then Touched. I tryed using Magnitude but the areas are so close to each other it would overlap. I tryed useing math by dividing the size adding added it one the position but that only works for blocks who’s orientation is 0,0,0. I was thinking of using Region3 but isn’t that for terrain and I don’t think I could see if the player is in it.
Region3 is for parts, not necessarily terrain. The way you’d check to see if players are inside is by looping every second or so, and every time you loop you iterate through all of the parts in workspace:FindPartsInRegion3(region), retreiving the player from the parts if possible.
I don’t have any direct source, but it doesn’t require either of those. There’s really clever and efficient algorithms for this if you search for “Point in polygon algorithm” on google. I don’t know how it works to a point where I’m confident to explain how it works, sorry.
A simple way to detect if players are in certain areas can be achieved by using part:GetTouchingParts(), this returns a list of all colliding parts based off of the actual hitbox of the part.
If you fill each region with can-collide false parts, you can use this method to find all players who are colliding with it, you can use that to carry out an action on all players within that region. Not sure exactly how intensive this is, but I assume not very. You could have a loop to do this, or just carry out the check when necessary.
Here’s a sample of the code you could use:
script.Parent.Touched:Connect(function()end) -- Can-collide false parts need a TouchInterest
local function getCollidingPlayers(part)
local colliding = {}
for _,obj in pairs(part:GetTouchingParts()) do
local plr = game.Players:GetPlayerFromCharacter(obj.Parent) -- Check if colliding part is a character's part
local found = false
for _,cPlr in pairs(colliding) do -- Make sure they're not already in the list
if cPlr == plr then
found = true
break
end
end
if not found then
table.insert(colliding,plr) -- Add them to the list
end
end
return colliding
end
while wait(0.2) do
local colliding = getCollidingPlayers(script.Parent)
if #colliding > 0 then
for _,plr in colliding do
-- Do stuff to all colliding players
end
else
-- No one is colliding
end
end
Here’s a sample place I used to check how well the collisions worked with this method: GetTouchingParts Example.rbxl (15.1 KB)
I’ll try but I am sure it will have the same problem as with the Touch event. Where whenever I equip a tool it retouches it and that’s a problem with the code I am working with.
Ah, I see. You only want an action to be carried out once each time a player enters a zone. You can still use the method, but you will have to carry it out another way. I’m only on mobile now so can’t really help.
Here’s what I’d do: create a master table, if someone’s not in it but they are in the colliding table then they have entered the area (carry out the action here and add them to the master table). If someone is in the main table but not in the collisions table then they must’ve left the region (carry out the leaving action if there is one and remove them from the master table), hope this helps, I’ll be able to provide some code tomorrow.
the two inPoint values are not the same because I measured it with my best guess and a red stripe. But it’s simi actuate. This is what you mean right? (edited(this does not work)
If your polygon is convex, you can just loop over the lines making up the polygon, and check that the point is on the same “side” of all of these lines. Check this diagram for example:
If you compute that the green point is on the “blue” side of every of the 3 lines making up the polygon, then you can conclude the green point is inside the polygon.
Note again, this only works for convex polygons, but if your polygons can only ever be convex (i.e. they are always either squares, rectangles, any triangle, uniform n-gons, or trapeziums), then you don’t need a more complicated algorithm.
This is extendable to 3d convex meshes too: just do the “is it on the right side” check for each face of the mesh
For a more sophisticated algorithm that handles arbitrary polygons, see here:
Each line has 2 points, from there you can create a CFrame for each line that lies on the line and points toward the blue direction, and then you can transform the green dot to the object space of that CFrame. Then it should be as simple as checking if that transformed dot has a negative Z position.
I’ve decided to spend a bit of time and came up with this solution for detecting players in a region using part:GetTouchingParts(). It works in the way I proposed earlier in this thread, all the code is available in the place in ServerScriptService. Players can only be in one region at a time (there’s no spam if they are in 2 regions) and there is a place to put your code for when players enter and leave regions (which fires only when they actually enter and leave).