Well, You used :Touched that relies on the user not doing anything, while getting the touching parts you basically just check if the user is there or not. not if it has moved
Ah, I’m sorry, I hadn’t thought about it.
Using maths:
- For a rectangular set a region in terms of x, y, z, w, h, l such that:
- x is the x position,
- y is the y position,
- z is the z position,
- w is the width of the rectangular region,
- h is the height of the rectangular region,
- l is the length of the rectangular region. - Then compare the value of the players parts parts of the body (you could use recursion on each body part) to see if it fits with all the boxes at all the vertexs of the part. If it does then at least 0.001 studs of the players body is within said region.
- You will have to use magnitude and radius for a circle alongside pythagoras in order to get pin point locations.
This is long though as maths in the third dimension is time consuming - doing that in my A Level project though and I’m predicted to do extremely well thanks to it as I’m not using a built in function.
The thing here is that you aren’t really supposed to use GetTouchingParts for a region check. This is reinventing the wheel for resolving functions to check if a position is within another via mathematical equations, using Region3 or whitelist downcasting to a region identifier. The workflows are the same but Touched involves more work because it is a function tied to the physics pipeline.
Touched is not really an accurate or good way to check for presence in a region.
How would I check whenever a player enters the area and exits it without touch? Would I infinitely loop code that checks if the player is in the area?
I think I’ll be using that code. I was just recently thinking about how to check if an NPC is in the area. So simple yet so brilliant. LOVE it. The exact type of code I can handle.
Something like that, yeah. You can check the coordinates of the character in 2D space (no height axis), unless you need regions across multiple floors as well which then you’ll need to do 3D space checking.
You can also alternatively set up region parts below the map and do a whitelisted downcast against those parts every frame (with STEPPED, not RenderStepped) to check what region part a player is at. You can then push changes if the region changes between the found value and the current.
An empty touched event for parts without collisions to make GetTouchingParts work is somewhat of an unsupported hack. Luckily it doesn’t cause undue physics simulation but now you’re taking up memory for a blank function which is also called every physics step when an intersection is found.
Why would I prefer detect player’s 2d space over 3d?
It’s use case dependent. In some cases, you may have regions in your world that are layered. For example, imagine a tower with two floors. Each of those floors you want a different region, yes? Therefore, you would need to work in 3D space, adding the Y coordinate, to determine what floor you’re on and thus determine a player region.
Now suppose you have that same tower but you have two regions: inside the tower and outside. You want the tower to be considered a region, regardless of how high the player is. We can then eliminate the need to check for any vertical axis and we can treat the entire X-Z space of the tower as a region.
The short of it is that when you have regions in different vertical heights, you want to check in 3D space. If you just have regions of a map and there doesn’t need yo be any layered regions (ground region plus some on top), we can just work in 2F space and ignore pointlessly accounting for height.
By the way, if you’re interested in region code because you want to make a sound system, SoundService.AmbientReverb has some great starter code you can reference from. It works in 3D space to define a cave ambient region, so anything above or below the cave is not part of the cave region but anything inside is.
Using the same scenario above: if we wanted to just make a whole section of the map a region regardless of where you were (even inside the cave), ignore height, just check 2D space. There are cases where you can combine them: you check 2D space X-Z for one region and Y to check for layered regions.
I need to have some pads the player can kinda step on but if they jump or are just above them then it won’t count as stepping off the pad, and I need stuff happening precisely when the player steps onto the pad and steps off, and my scenario isn’t layered
I have a function that lets you check if a vector3 position is above a part’s position:
local function posAbovePart(pos, part)
local siz = part.Size
local opos = CFrame.new(pos):ToObjectSpace(part.CFrame)
local c1 = false
local c2 = false
if math.abs(opos.X) < siz.X/2 and math.abs(opos.Z) < siz.Z/2 and opos.Y < 0 then
return true
else
return false
end
end
Do I just loop it constantly to check if a player is on or not? Is that a good idea performance-wise?
Is looping code constantly infinitely a good idea in general? (I’ve never been in such a scenario before)
Ah, so you want to work with 3D space in this case then. What’s your use case: are you intending to make a sort of effect pad? Yeah, it’d be more understandable if you wanted to stick with a physics-based event then.
In terms of looping, you can cut costs immensely by only using a vector check only if a player is near a pad. That way, each iteration the engine performs an inexpensive distance check between a point and your pad’s position: if the point is near the pad, then it can perform the vector check.
The only real expense I see in your code is the creation of a new CFrame which leads me to confusion as to why you don’t do a raw comparison for a passed CFrame. You shouldn’t need to do object construction at all. That aside, nothing else is really expensive here.
Loops are fine. Just use them sparringly and rely more on events, such as from RunService. lso avoid looping where not necessary or preventing heavier operations from running if lighter ones do not pass.
Is there a way I can get events that fire when player enters the pad or exits it?
You’ll either have to create your own events or continue using the originally marked solution, I’m afraid.
You said using the I don’t need to use the physics engine, that can be innacurate or ineffective or whatever. What would be a better solution in my case: Using the touch and gettouchedparts events or using the stepped event to loop the position check?
That would be fixed with a simple debounce.
Debounce not worked, trust me. Now i would use the Zone+ Module mady by @ForeverHD, its really easy and helpfull.
Do you know how I could go about regions based on position?
Hey thanks for your reply, does this also work with unions?
Yeah, it should work with unions (and any other part that can be collidable).
This code here will detect when a player is inside a part, and when the player leaves the part.
The code will be repeated but I suggest you modify what I made using debounce
Edit: I added in debounce for simplicity; it was a lot trickier to code than I thought.
-- local script
local Part = game.Workspace:WaitForChild("Vent1").Detect -- The part you want to detect
local tbl = {}
local debounce = false
local debounce2 = false
game:GetService("RunService").Heartbeat:Connect(function(loop) -- Heartbeat loop
task.wait()
if #tbl == 0 then -- if there isnt anything in table
if not debounce2 then
debounce2 = true
print("Player Outside Part") -- run code
debounce = false
end
end
if #tbl ~= 0 then -- if there is a part in table
if not debounce then
debounce = true
task.wait()
print("Player Inside Part") -- run code
debounce2 = false
end
table.remove(tbl, 1) -- removes the part from table
end
Part.Touched:Connect(function() end) -- creates a touch interest
local prt = Part:GetTouchingParts()[1] -- gets the touching parts of the specified part
table.insert(tbl, prt) -- inserts the part into table
end)