Region3 is driving me insane

I have this script

ServerScript:

local players = game:GetService("Players")
local Regions = workspace:WaitForChild("Regions")
for i,v in pairs(Regions:GetChildren()) do
	v.Transparency = 1
	v.CanCollide = false
	v.Anchored = true
end

function CreateRegion3FromPart(Part)
	return Region3.new(Part.Position-(Part.Size/2),Part.Position+(Part.Size/2))
end

function GetPlayersInPart(part)
	local region = CreateRegion3FromPart(part)
	local partsInRegion = workspace:FindPartsInRegion3(region,nil,math.huge)
	local Players = {}
	for _,Part in pairs(partsInRegion) do
		local player = game.Players:GetPlayerFromCharacter(Part.Parent)
		if player then
			table.insert(Players,player)
		end
	end
	return Players
end

while wait(0.5) do
	for i,region in pairs(Regions:GetChildren()) do
		local plrs = GetPlayersInPart(region)
		for i,v in pairs(plrs) do
			game.ReplicatedStorage.RemoteEvents.Remote11:FireClient(v, region)
		end
	end
end

The regions are inaccurate. I’ve made sure orientation is 0,0,0 since Regions can’t be rotated BUT STILL
it will randomly say the player is somewhere they aren’t. All the remote event does when it’s received by the client is change a text GUI to tell them their location and change fog. I’ve confirmed the client isn’t the cause with some debugging. Somebody, please tell me what I’m doing wrong, my game has been going great up until now and this is extremely demotivating. If there’s any other needed information (other than the local script) let me know.

1 Like

Hey,

I was literally coding this earlier today lol. And yeah your Region3’s might not be correct, try this :

local corner1 = Vector3.new(part.Position.X - part.Size.X / 2, part.Position.Y, part.Position.Z - part.Size.Z / 2)
local corner2 = Vector3.new(part.Position.X + part.Size.X / 2, part.Position.Y + 200, part.Position.Z + part.Size.Z / 2)
local sampleRegion = Region3.new(corner1, corner2)

The 200 added to the Y is to make the height of the Region3 large. You can lower the height according to your needs though.

Testing this now, thank you so much in advance if it fixes the problem!

If I just remove the + 200 will that break it? That’s a lot of text, I’m tired and don’t feel like reading it all- just taking your word

I replaced the function with this:

function CreateRegion3FromPart(part)
	local corner1 = Vector3.new(part.Position.X - part.Size.X / 2, part.Position.Y, part.Position.Z - part.Size.Z / 2)
	local corner2 = Vector3.new(part.Position.X + part.Size.X / 2, part.Position.Y, part.Position.Z + part.Size.Z / 2)
	return Region3.new(corner1, corner2)
end

And it now nothing happens when I enter the area

You have no volume on the Y axis. You need to do a +/- on each of those lines for the Y axis. Give it maybe 10 studs or however much you think it needs to be to get all of the characters in there.

1 Like

Are the parts cubes? I wrongly assumed they’d be flat since that was what I last worked on.

If the parts are cubes, then you’d have to offset the y similarly to the x, and z.

Yeah, this too. Didn’t catch that.

I want the region size the exact size of the parts. Each part is a different size and are not cubes
Edit: Exact size and position

image
This is an example of some regions (the black parts)

I didn’t mean cubes like that (just meant if you are using the exact size). But you could try specifying each component of the vector. I’m not sure if this would yield a different result than your old function, but might be worth trying :

function CreateRegion3FromPart(part)
	local corner1 = Vector3.new(part.Position.X - part.Size.X / 2, part.Position.Y - part.Size.Y  / 2, part.Position.Z - part.Size.Z / 2)
	local corner2 = Vector3.new(part.Position.X + part.Size.X / 2, part.Position.Y + part.Size.Y / 2, part.Position.Z + part.Size.Z / 2)
	return Region3.new(corner1, corner2)
end

Still breaks. It tells me I’m in a location I’m nowhere near

That’s odd. One thing though, if you’re already keeping a part there, why not use .Touched and TouchEnded?

That’s just an alternative though, but the performance may be better than infinitely looping and checking every region.

This is what I did which is very similar to your script albeit some differences. It worked for me:


-- Retrieves a table of HRP's of players that are currently loaded
local function GetPlayerHRPs()
	local tab = {}
	for _, player in pairs(Players:GetPlayers()) do
		local char = player.Character
		if char then
			local hrp = char:FindFirstChild("HumanoidRootPart")
			if hrp then
				table.insert(tab, hrp)
			end
		end
	end
	return tab
end

-- Finds players given a table of humanoid root parts
local function FindPlayersFromHRP(currentHRP)
	local playerTab = {}
	for _, hrp in pairs(currentHRP) do
		local plr = Players:GetPlayerFromCharacter(hrp.Parent)
		if plr then
			table.insert(playerTab, plr)
		end
	end
	return playerTab
end


-- Subtracts two sets
local function SetSubtract(tab1, tab2)
	local tab3 = {}
	
	for _, v in pairs(tab1) do
		if not table.find(tab2, v) then
			table.insert(tab3, v)
		end
	end
	return tab3
end

-- Initialize all the Region3 and table instances
local function InitializeTables()
	for _, plot in pairs(plots:GetChildren()) do
		local plotBase = plot.Plot
		
		local corner1 = Vector3.new(plotBase.Position.X - plotBase.Size.X / 2, plotBase.Position.Y, plotBase.Position.Z - plotBase.Size.Z / 2)
		local corner2 = Vector3.new(plotBase.Position.X + plotBase.Size.X / 2, plotBase.Position.Y + 200, plotBase.Position.Z + plotBase.Size.Z / 2)
		
		local newRegion = Region3.new(corner1, corner2)
		
		Region3Table[plot] = newRegion
		PlotPlayer[plot] = {}
	end 
end	

-- Check player movement
local function ScanPlayerMovement()
	for plot, region3 in pairs(Region3Table) do
		local currentHRP = workspace:FindPartsInRegion3WithWhiteList(region3, GetPlayerHRPs())
		local currentPlayers = FindPlayersFromHRP(currentHRP)
		
		local newPlayers = SetSubtract(currentPlayers, PlotPlayer[plot])
		local leftPlayers = SetSubtract(PlotPlayer[plot], currentPlayers)
		
		for _, player in pairs(newPlayers) do
			print(player.Name.." entered.")
		end
		
		for _, player in pairs(leftPlayers) do
			print(player.Name.." left.")
		end
		
		PlotPlayer[plot] = currentPlayers
	end
end

--[[ INIT ]]--

-- Initializes all the Region3's
do
	InitializeTables()
end

-- Infinitely loops and checks player movement between region3's
do
	while wait(ITER_DELAY) do
		ScanPlayerMovement()
	end
end

Apologies for the long script, but this detects both Touch and Touchended equivalent for Region3

Are the parts rotated? Your region3 code doesn’t work for rotated parts.

Orientation is 0,0,0. Unless something else indicates rotation then no

Are the parts anchored in the workspace before this script runs?

Yeah, and again in the script- on the script above you sent, where do I initialize the PlotPlayer and Region3Table variables, and as what? Or like, what are they supposed to be?

image

declare those missing variables as tables

1 Like
local Region3Table = {}
local PlotPlayer = {}

-- Retrieves a table of HRP's of players that are currently loaded
local function GetPlayerHRPs()
	local tab = {}
	for _, player in pairs(Players:GetPlayers()) do
		local char = player.Character
		if char then
			local hrp = char:FindFirstChild("HumanoidRootPart")
			if hrp then
				table.insert(tab, hrp)
			end
		end
	end
	return tab
end

-- Finds players given a table of humanoid root parts
local function FindPlayersFromHRP(currentHRP)
	local playerTab = {}
	for _, hrp in pairs(currentHRP) do
		local plr = Players:GetPlayerFromCharacter(hrp.Parent)
		if plr then
			table.insert(playerTab, plr)
		end
	end
	return playerTab
end


-- Subtracts two sets
local function SetSubtract(tab1, tab2)
	local tab3 = {}

	for _, v in pairs(tab1) do
		if not table.find(tab2, v) then
			table.insert(tab3, v)
		end
	end
	return tab3
end

-- Initialize all the Region3 and table instances
local function InitializeTables()
	for _, plot in pairs(Regions:GetChildren()) do
		local plotBase = plot

		local corner1 = Vector3.new(plotBase.Position.X - plotBase.Size.X / 2, plotBase.Position.Y, plotBase.Position.Z - plotBase.Size.Z / 2)
		local corner2 = Vector3.new(plotBase.Position.X + plotBase.Size.X / 2, plotBase.Position.Y + 200, plotBase.Position.Z + plotBase.Size.Z / 2)

		local newRegion = Region3.new(corner1, corner2)

		Region3Table[plot] = newRegion
		PlotPlayer[plot] = {}
	end 
end	

-- Check player movement
local function ScanPlayerMovement()
	for plot, region3 in pairs(Region3Table) do
		local currentHRP = workspace:FindPartsInRegion3WithWhiteList(region3, GetPlayerHRPs())
		local currentPlayers = FindPlayersFromHRP(currentHRP)

		local newPlayers = SetSubtract(currentPlayers, PlotPlayer[plot])
		local leftPlayers = SetSubtract(PlotPlayer[plot], currentPlayers)

		for _, player in pairs(newPlayers) do
			print(player.Name.." entered.")
		end

		for _, player in pairs(leftPlayers) do
			print(player.Name.." left.")
		end

		PlotPlayer[plot] = currentPlayers
	end
end

--[[ INIT ]]--

-- Initializes all the Region3's
do
	InitializeTables()
end

-- Infinitely loops and checks player movement between region3's
do
	while wait(0.5) do
		ScanPlayerMovement()
	end
end

I have this and it doesn’t work