Determining Player Location

Hello developers, today I have a question for y’all that needs solving:

You have 24 players maximum. One trampoline shaped like an octagon. You need to determine which players are inside this trampoline’s “launch space” (the octagon shape) when it launches. What’s the most efficient way to check an oddly shaped area like this?

Obligatory image

1 Like

If it’s (a series of) part(s), raycasting
Otherwise, storing a bunch of Vector3 nodes and checking each player’s position and seeing if they’re within the region

2 Likes

You could send a raycast from the character to the ground and see if it hits the octagon or not

Edit: Ugh tenal beat me by a few seconds

2 Likes

It’s a series of parts (wedges and parts), so I think this may be the best option. I recall Raycasting was very expensive on Roblox years ago, but I hope nowadays it wouldn’t be too taxing to run 24 raycasts like that every ~30 seconds or so.

1 Like

They are actually very cheap (Source: https://devforum.roblox.com/t/raycasting-performance/14897/2)

1 Like

Alternatively @1waffle1 has an awesome regioning system that just uses clever math (whether num intersections is odd/even) to determine whether a position is within a closed region with arbitrary size/num edges.

1 Like

The octagon is restricted by 8 lines. Assume you extend these lines infinitely in each direction. For each line, it is easy to say whether the player is on one side of the line or the other. Using that fact, you just have to check if the player is on all right sides of all lines, and if so, they will be inside the octagon. If they are on the wrong side of one or more of the lines, they are not inside the octagon.

This also easily extends to other kinds of convex shapes.

(Note: It does not work this trivially for concave shapes. For those, you first need to split them in two convex shapes and do the same tactic, or use a different method)

2 Likes

Do you think the raycasting is optimal, or 1waffle1’s method? Or is what you’re suggesting something entirely different?

You will have a much easier time just using roblox’s built in raycasting than doing the math involved in @buildthomas’ answer. There is absolutely no reason to worry about the performance impact of doing 24 raycasts every 30ish seconds - it’s completely negligible.

Because it’s a very regular shape, you can normalize the “octrant” the position is in to a single “octrant” (i.e. the modulo in the function below). That way, you only need to check the side of a single line:

local function is_in_octo(inrad, x, y)
	local frac_to_edge = math.cos(math.atan2(y, x) % (math.pi / 4) - math.pi / 8)
	return frac_to_edge * (x*x + y*y) <= inrad*inrad
end

Raycasting is probably fast enough though :stuck_out_tongue: .

4 Likes

If you have an octagonal base, you may as well raycast. I didn’t know if you did though, so I just gave a generic algorithm for convex zones.

1 Like

build the collision box for the trampoline out of anchored, cancollide parts (wedge parts, part parts, or meshparts all work). similarly, use an anchored, cancollide part to represent each character’s bounding box. have all of these parts in collision groups set up so that they can only collide with eachother. then, use :GetTouchingParts() to detect if any character parts are touching the trampoline parts. this solution has low impact on preformance and is probably one of the easiest to implement

local octagonCollisionParts   = {}
local characterCollisionParts = {}

function getCharactersOnTrampoline()
	local charactersOnTramp = {}
	for _,collisionPart in pairs(octagonCollisionParts) do
		for _, playerPart in pairs (collisionPart:GetTouchingParts()) do
			local player = characterCollisionParts[playerPart]
			charactersOnTramp[#charactersOnTramp+1] = player.Character
		end
	end
	return charactersOnTramp
end