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