Detect if a player is inside a certain area

Hello,
I’m trying to detect if a player is in this village:

I first tried doing it by placing a giant cylinder over the entire thing and making a value true/false based on the touched and touchended event, like this:

Detect.Touched:Connect(function(Part)
if Part.Name == ‘HumanoidRootPart’ then
print(‘entering’)
local Character = Part.Parent
local player = Players:GetPlayerFromCharacter(Character)
local InVillage = player:WaitForChild(‘Saves’):WaitForChild(‘InVillage’)
InVillage.Value = true
end
end)

Detect.TouchEnded:Connect(function(Part)
if Part.Name == ‘HumanoidRootPart’ then
print(‘leaving’)
local Character = Part.Parent
local player = Players:GetPlayerFromCharacter(Character)
local InVillage = player:WaitForChild(‘Saves’):WaitForChild(‘InVillage’)
InVillage.Value = false
end
end)

But it didn’t work because the player spawns in the village, causing weird things like the value seemingly randomly switching on and off. How else could I detect which players are inside the village (preferably server-sided?)

2 Likes

What you could is, add a box covering the whole village and make it invisible.


Players.PlayerAdded:Connect(function(plr)
    
Box.Touched:Connect(function(hit)
        if hit then
            plr:WaitForChild(---- your script

end)
end)

(Also you can’t change anything on a client using a script unless you are firing a remote event)

If you want to use parts to define your regions, you can use :GetTouchingParts().

GetTouchingParts() will return all the parts that some given part is colliding or intersecting with. It will not detect CanCollide = false parts, unless you have a .Touched connection on the base part or the non-cancollide part.
You can then iterate through the list it returns until you find a part that defines a region, or if you exhaust the list you can assume that you are not in any region.

An example function would be:

function get_in_part(HumanoidRootPart,VillagePart)
    local c = HumanoidRootPart.Touched:Connect(function() end) -- This is just to make sure it detects non-cancollide parts
    local parts = HumanoidRootPart:GetTouchingParts()
    c:Disconnect()
    
    for i, k in ipairs(parts) do
        if k == VillagePart then
            return true
        end
    end
    
    return false
end
5 Likes

I personally really like to use this module by ForeverHD. I could explain how to use it, but he already made a good example. Just take a look at it and I promise you it’ll be worth it :wink:

1 Like

You can use Region3 instead.

Or rotated region3 with a lot more feature

And you should learn about Region3 and stuffs to do that

Thought I’d expand on what others have said in this post. There is currently a really nice module released @ForeverHD. I’ve personally used it and it handles things like area entry and exit really well. It combines the use of Raycasting and Region3.

@daireb

I worked this out using your suggestion:

while true do
wait()
local HumanoidRootPart = player.Character.HumanoidRootPart
local c = HumanoidRootPart.Touched:Connect(function() end)
local parts = HumanoidRootPart:GetTouchingParts()
c:Disconnect()
for i, k in ipairs(parts) do
if k.Name == ‘VillageDetect’ then
if player:WaitForChild(‘Saves’):WaitForChild(‘InVillage’) ~= true then
local Update = ‘Update’
local Value = true
remote:FireServer(Update,Value)
end
end
end
end

It works so far but I don’t know where to put the event to set the value to false.

@Thanhpro291368
As far as I know, you can only make sqaure region3s and I went with this one because I could use a cylindrical shape.

@ClientScripts @Nova_MrRoyal
I went the easy route using the way described above because it seems to work just as well, please tell me if that method is better, I will definitely investigate it.

ps, how do you write Lua code in a post? I’m quite new and can’t figure it out.

Thanks for the help!

What you want to do is just have a variable outside your loop that can be initially set to false.
Inside the loop, if you find that you’re in the village, set it to true, and break from the loop.
Then afterwards you can just check the variable, since if it never found the “VillageDetect” part it will be false, and if it did it will be true.
So:

if found then
    blah blah whatever you do if you are in a village
else
    blah blah whatever you do if you are not in a village
end

Another way detection can be done is through magnitude. This can find the distance between two points. You could use something along the lines of “if the magnitude from a point (part) at the center of town to the player’s root part is less than distance in number, then player is in the village.” I believe this would make a spherical area around the part in the center.

It works!

Here’s the final script if you’re curious:

while true do
print(‘running’)
wait()
local HumanoidRootPart = player.Character.HumanoidRootPart
local c = HumanoidRootPart.Touched:Connect(function() end)
local parts = HumanoidRootPart:GetTouchingParts()
c:Disconnect()
for i, k in ipairs(parts) do
if k.Name == ‘VillageDetect’ then
Result.Value = true
break
else
Result.Value = false
end
end
end

Result.Changed:Connect(function(Value)
if Value == true then
local Update = ‘Update’
local Value = true
remote:FireServer(Update,Value)
elseif Value == false then
local Update = ‘Update’
local Value = false
remote:FireServer(Update,Value)
end
end)

Thanks for all the help!

@daireb

It does change itself to false for a very short time while looking through the parts list, could that have an effect if I later use an if statement on the value. It changes so rapidly you don’t even see it, but I do see it when I print true or false when it’s changed.

Your code will always run in the same order, so as long as you’re sure it’s finished being set before you check it, you won’t have any issues.

anyways, this is the final version without any problems:

while true do
wait()
local HumanoidRootPart = player.Character.HumanoidRootPart
local c = HumanoidRootPart.Touched:Connect(function() end)
local parts = HumanoidRootPart:GetTouchingParts()
c:Disconnect()
local Amount = #parts
for i, k in ipairs(parts) do
Amount = Amount - 1
if k.Name == ‘VillageDetect’ then
Result.Value = true
break
elseif Amount == 0 then
Result.Value = false
break
end
end
end

-- That's how you write lua Code

grafik

You can use Markdown to format your posts. Just search for it in the internet an you’ll find what possibilities you have :happy1:

ZonePlus v3.2.0 | Construct dynamic zones and effectively determine players and parts within their boundaries Is the best option and latest!