As a Roblox developer, it is currently too difficult to find which room a character is in at any given time, when the rooms are irregularly shaped. Let me explain:
So regular, cuboid shaped rooms aren’t a problem - if it’s not rotated, you can just use GetPartsInRegion3 or one of its derivatives; if it is rotated, you somehow check manually (I can’t figure out how to go about doing that off the top of my head – sorry!). Similar story with cylindrical and spherical rooms (though with spherical you can disregard rotation altogether).
I suggest a function that takes a part/union/meshpart (or multiple parts?) and returns whatever parts are within the passed volume, respecting collision fidelity of unions and meshparts, as well as blacklist and whitelist variations.
Use case: I have irregularly shaped rooms in my game (a cooperative spacecraft management game), and I want to know which room a given character is in at any given time, so I can check if they’re being subject to extremes of temperature/pressure/whatever (in case of depressurisation, etc.), as well as let the captain check crew positions.
Can’t really do that - last I tried that, it was unreliable and often failed to recognise when someone started to pass through the door but turned around, or glanced past it. I’m probably also going to introduce damage modelling (so large holes will appear in corridors if the ship takes serious damage), which may complicate things.
You can’t really expect Roblox to develop features that are too difficult for you to develop yourself. Part of game dev is overcoming these obstacles and learning from them even if they are complicated.
Google “find point inside polygon” and you can try and learn how it’s done that way, you’ll learn much more that way
My main concern is performance: I know a few ways I could do it (though admittedly there would be a lot of trial and error involved), but this is something I would have to run several times a second to achieve the desired effects. Having a built-in function to do this not only makes this far easier, but may be a far better option performance-wise.
Edit: After Googling, all I can find are obfuscated libraries that offer this in other languages, poorly documented examples and examples described in completely opaque terms. Damnit Jim, I’m a layman, not a mathematician!
The best solution for this right now would be to use GetTouchingParts. I don’t know what the performance of it is, but it this covers most of what you want…
I’m pretty sure it covers mesh/csg fidelity too, but I’m not sure. It doesn’t seem to respect collision filters, but you can write your own API to add whitelists/blacklists.
I don’t imagine this is a huge performance drain, but it isn’t as good as a dedicated API for checking regions would be. I think this feature would be a great and simple addition. Maybe even as simple as an option passed to GetTouchingParts like AssumeCanCollideTrue(or even ignoring when CanCollide is false in the first place), so that there doesn’t need to be expensive property changes.
Simple example:
function isInRegion(regionPart)
local wasCanCollide = regionPart.CanCollide
regionPart.CanCollide = true
local result = regionPart:GetTouchingParts()
regionPart.CanCollide = wasCanCollide
return result
end
I don’t know how this compares to GetTouchingParts, but…
I use this function to get if a part centroid is inside a rotateable rectangular region:
local IsInsidePart do
local P2OS = CFrame.new().pointToObjectSpace
function IsInsidePart(part,point)
local relativePosition = P2OS(part.CFrame,point)
local size = part.Size
if relativePosition.X*relativePosition.X <= size.X*size.X*0.25 and relativePosition.Y*relativePosition.Y <= size.Y*size.Y*0.25 and relativePosition.Z*relativePosition.Z <= size.Z*size.Z*0.25 then
--square is fast absolute value
return true, relativePosition
else
return
end
end
end
The part does not need to be inside the workspace, which I think is fortunate.
First off, it’s not clear to me exactly how irregular your rooms are. Depending on the true geometry, you can take shortcuts. For example, if all of the rooms can be reduced to a set of boxes, then it’s easy. Just see the example @NWSpacek listed.
You can check a point against an arbitrary convex shape pretty easily. You represent the shape as an array of planes in the form Ax + By + Cz + D = 0, and you iterate through it. For any of the planes, if the formula produces a positive number when evaluated with the point, it is outside the shape.
To get arbitrary room shapes, you have to perform convex decomposition. This is trickier. I don’t know of an easy way to do this off the top of my head, other than creating a BSP tree. (The leaves of a BSP tree are convex hulls.)
Representing faces in plane form is somewhat unintuitive at first. You can construct standard form (Ax + By + Cz + D = 0) from a point on the face and its surface normal vector using ABC = normal.xyz, D = -normal:Dot(point). Note that Roblox does not give you access to face data of CSG or mesh parts.
I’ve had to implement separating axis theorem (for testing collisions between two oriented boxes) in the past. It was plenty performant, as long as I did a broadphase pass first using GetPartsInRegion3 of the AABB of one of the boxes.
Also, this is a client feature, not a studio feature.
I didn’t understand most of what you said there (like I said, I’m basically a layman when it comes to mathematics), but I gleaned more from it than I did an entire set of Google searches. Thanks.
Moved this thread to client features – my mistake.
Can you not have parts or meshes formed into the shapes of the rooms, make them invisible and have them welded into the room floor. From here, using a ray with a whitelist of only those invisible floor parts, shoot the ray down from the character and see if it hits any floor parts. From the hit floor part you can then conclude which room it is by naming each floor part to it’s corresponding room or something.