How do you check if the player is in certain area

If this is only based on regions as a plane, as in, not a 3d shape like a sphere or a cuboid, you could use a point in polygon algorithm.

But region3 is for squares and I have a area that’s shaped as a wedge.

I don’t know trigonometry or calculus yet so if it’s that really science stuff I’ll need someone to explain it to me. Send link of it.

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.

1 Like

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)

8 Likes

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.

Ok after about a hour I Cebu up with this diagram. Is this what you mean and if not will it work anyway?

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)

3 Likes

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:

image

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:

7 Likes

How do I find out if it’s on the blue side? Should a take the position of the area part and use :toObjectSpace?

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.

4 Likes

won’t my idea take less code using magnitude?

I don’t think that method works for arbitrary convex shapes, only for a subset of them.

Yeah but all I have is Wedges and Parts.

There’s your problem. :stuck_out_tongue: I believe your code only works for equilateral convex shapes.

Wedges are only haft a square so could i not just take away one of the corners?

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).

Here’s the place: Region Test.rbxl (16.5 KB)

I hope this helps, it saves you having to do complicated maths to detect players within an irregularly shaped region.

6 Likes

Thanks but I already finished the code.

Ive messed around with your Script, it is indeed very accurate, But, i have found a issue with it, it seems, that in some cases it isnt capable of detecting when a player leaves a area, in my case, i have linked it to a system that plays music and shows a gui on screen when a player enters a area, but sometimes, it just does not detect when the player leaves and the music keeps going forever

Any idea of how i could fix this issue, it is a problem, since my game is suposed to run with 50 player servers and only having two players breaks it

1 Like

I have checked how I did it… I used GPS :slight_smile:

local The_Player_3D
The_Player_3D = The_Player.Character
local Player_Pos_V3 = The_Player_3D.HumanoidRootPart.Position

if Player_Pos_V3.X > 276 then
   if Player_Pos_V3.X < 290.5 then
      if Player_Pos_V3.Y < -358 then
         if Player_Pos_V3.Y > -381.5 then
            if Player_Pos_V3.Z > -1050.5 then
               if Player_Pos_V3.Z < -1012 then
                   -- the player is in the designated area
               end
            end
         end
      end
   end
end
2 Likes