Hi, so I was working on finding an ideal way for figuring out whether or not a player is in a store building, and the store is quite large. I’ve tried tons of other options, including Region3s, which Roblox has serious limitations on their volume making that a flop. I also tried :GetTouchingParts() on each boundary part directly, but that causes massive hitching and it’s a hacky and poorly optimized method, obviously.
And now, the most ridiculous thing I’ve come across is the fact apparently rays don’t hit any part the player is actually inside of. I tried using raycasting for this because it’s lightweight and clearly the best option, but I would’ve never expected this outcome. It works if I cast a ray at the player’s torso position in the direction of their character, but if I try casting a ray straight up from the player’s head and the player’s inside of the actual boundary part, it hits nothing and returns nil.
Any help appreciated, thanks. Crazy how absolutely nothing works.
Have you tried using a Collision Group that is just intended for “Location Identifiers”? Since you can set for a custom Collision Group in the RaycastParms.
Possibly consider putting your marker boxes below the map thus making it not have issues with the player being already inside the part and then having it return nil.
If all you’re looking for is players and the area is large, then Workspace:FindPartsInRegion3, Part:GetTouchingParts etc. are horrible choices in such a case because to use them, you find every single part in the region and check whether any of them are the player. You’re doing a LOT more work than you should be.
You would want to use these methods that return every part, if you really want to find every part in an area. But you are discarding everything that isn’t the player, so of course it’s unreasonably slow.
Instead, just compare coordinates.
Find the position of the player, and the two corners of the region (just like Region3). If the player’s X is between the Xes of the corners, Y between the corners etc., then the player is in the region. You are doing thousands of times less work this way.
If the store is rotated, you can read one of my earlier posts to know how to check where a point is in relation to an arbitrarily rotated rectangle (or even a part, if you use the 3rd dimension!).
edit: the suggestion in the thread I linked essentially does the same thing as the code below, except PointToObjectSpace does it in 3D and is in a convenient little function
Speaking of the 3rd dimension, you can know where a point is in relation to a part with CFrame:PointToObjectSpace, which will transform a point into the CFrame’s worldview. i.e. if there is a Part that’s exactly 5 studs in front of a Torso, then Torso.CFrame:PointToObjectSpace(Part.Position) will be exactly Vector3.new(0, 0, 5) regardless of where either of them are.
Some code, since I got carried away writing this:
local part -- part that covers the store
local size = part.Size
local cf = part.CFrame
-- the store probably won't move, so these can stay static and the part can be cleaned up
part:Destroy()
part = nil
local point = Vector3.new(4, 5, 9) -- position of the player
local relative = cf:PointToObjectSpace(point) -- position of player relative to region
if
math.abs(relative.X) < size.X
and math.abs(relative.Y) < size.Y
and math.abs(relative.Z) < size.Z
then
print("Player's center point is in the part")
end