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