` I am trying to program a function which detects if a player is in a region3. If the player is in the region3, it fires one event, but if the player is not in the region3, it fires a different event. This works by making a table of all of the players inside of the region and finding out which players aren’t on the list. By far it has worked consistently for one player, but once multiple players are involved it starts saying that the player is both inside of the table and not inside of it?
` This is a strange bug. I’ve even tried making my own iteration function and it still will not work properly.
In the screenshot it shows that Player1 and Player2 are clearly both in the list, but right below it says that Player 2 is not in the region. Here is the code I wrote:
local PlayEvent = game.ReplicatedStorage:FindFirstChild('MusicEvent') --Defining events
local StopEvent = game.ReplicatedStorage:FindFirstChild('StopEvent')
-- The values for the region3
local Zone = game.Workspace.MusicZones.Zone1
local min = Vector3.new(Zone.Position.X-Zone.Size.X/2, Zone.Position.Y-Zone.Size.Y/2, Zone.Position.Z-Zone.Size.Z/2)
local max= Vector3.new(Zone.Position.X+Zone.Size.X/2, Zone.Position.Y+Zone.Size.Y/2, Zone.Position.Z+Zone.Size.Z/2)
local region = Region3.new(min,max)
-- This was the iteration function I used before. I'm not currently using it but it's here for reference
local function Contains(Table, Value)
for i, v in pairs(Table) do
if v.Name == Value.Name then
return true
end
end
end
-- Main loop
while wait(0.5) do
local min = Zone.Position - Zone.Size*.5 -- Getting the size of the zone
local max = Zone.Position + Zone.Size*.5 -- Getting the size of the zone
local partInRegion = workspace:FindPartsInRegion3(region, nil, math.huge) --Find the parts
local playersInRegion3 = {}
for _, part in pairs(partInRegion) do
if part.Parent:FindFirstChild("Humanoid") ~= nil then
local plr = game.Players:FindFirstChild(part.Parent.Name)
if not table.find(playersInRegion3,plr) then
PlayEvent:FireClient(plr,Zone.Music)
end
table.insert(playersInRegion3,plr)--putting the player in the table
end
end
for _, Player in pairs(game.Players:GetChildren()) do
if table.find(playersInRegion3, Player) == nil then --checking if player is not in the table
print(Player.Name.." is not in region3")
StopEvent:FireClient(Player)
end
print(playersInRegion3)
playersInRegion3 = {} --resetting the table after every loop
end
end
That adds to the code readability (Idk why I didn’t think of using it at the time lol) but it ultimately does the same thing as my original buggy code.
So from what I see, you seem to be inserting the player for each part in the region, which is all the parts in the player. Why don’t you filter for HumanoidRootParts and also check if an instance of the same player is in the table? Like:
if part.Name == "HumanoidRootPart" and part.Parent:FindFirstChild("Humanoid") then
--Do stuff
end
Aka only doing one insert, because there’s only one HumanoidRootPart.
local PlayEvent = game.ReplicatedStorage:FindFirstChild('MusicEvent') --Defining events
local StopEvent = game.ReplicatedStorage:FindFirstChild('StopEvent')
-- The values for the region3
local Zone = game.Workspace.MusicZones.Zone1
local min = Vector3.new(Zone.Position.X-Zone.Size.X/2, Zone.Position.Y-Zone.Size.Y/2, Zone.Position.Z-Zone.Size.Z/2)
local max= Vector3.new(Zone.Position.X+Zone.Size.X/2, Zone.Position.Y+Zone.Size.Y/2, Zone.Position.Z+Zone.Size.Z/2)
local region = Region3.new(min,max)
-- This was the iteration function I used before. I'm not currently using it but it's here for reference
local function Contains(Table, Value)
for i, v in pairs(Table) do
if v.Name == Value.Name then
return true
end
end
end
-- Main loop
while wait(0.5) do
local min = Zone.Position - Zone.Size*.5 -- Getting the size of the zone
local max = Zone.Position + Zone.Size*.5 -- Getting the size of the zone
local partInRegion = workspace:FindPartsInRegion3(region, nil, math.huge) --Find the parts
local playersInRegion3 = {}
for _, part in pairs(partInRegion) do
if part.Name == "HumanoidRootPart" and part.Parent:FindFirstChild("Humanoid") then
local plr = game.Players:FindFirstChild(part.Parent.Name)
if not table.find(playersInRegion3,plr.Name) then
PlayEvent:FireClient(plr,Zone.Music)
end
table.insert(playersInRegion3,plr.Name)--putting the player in the table
end
end
for _, Player in pairs(game.Players:GetChildren()) do
if table.find(playersInRegion3, Player.Name) == nil then --checking if player is not in the table
print(Player.Name.." is not in region3")
StopEvent:FireClient(Player)
end
print(playersInRegion3)
playersInRegion3 = {} --resetting the table after every loop
end
end
Adding on. You seem to be inserting Instances into the table, which does work, but those instances might change some of the time which makes doing Player.Name a bit better. Try that.
local PlayEvent = game.ReplicatedStorage:FindFirstChild('MusicEvent') --Defining events
local StopEvent = game.ReplicatedStorage:FindFirstChild('StopEvent')
-- The values for the region3
local Zone = game.Workspace.MusicZones.Zone1
local min = Vector3.new(Zone.Position.X-Zone.Size.X/2, Zone.Position.Y-Zone.Size.Y/2, Zone.Position.Z-Zone.Size.Z/2)
local max= Vector3.new(Zone.Position.X+Zone.Size.X/2, Zone.Position.Y+Zone.Size.Y/2, Zone.Position.Z+Zone.Size.Z/2)
local region = Region3.new(min,max)
-- This was the iteration function I used before. I'm not currently using it but it's here for reference
local function Contains(Table, Value)
for i, v in pairs(Table) do
if v.Name == Value.Name then
return true
end
end
end
-- Main loop
while wait(0.5) do
local min = Zone.Position - Zone.Size*.5 -- Getting the size of the zone
local max = Zone.Position + Zone.Size*.5 -- Getting the size of the zone
local partInRegion = workspace:FindPartsInRegion3(region, nil, math.huge) --Find the parts
local playersInRegion3 = {}
for _, part in pairs(partInRegion) do
if part.Name == "HumanoidRootPart" and part.Parent:FindFirstChild("Humanoid") then
local plr = game.Players:GetPlayerFromCharacter(part.Parent)
if not playersInRegion3["ID"..plr.UserId] then
PlayEvent:FireClient(plr,Zone.Music)
end
playersInRegion3[#playersInRegion3 + 1] = "ID"..plr.UserId --putting the player in the table
end
end
for _, Player in pairs(game.Players:GetChildren()) do
print(playersInRegion3["ID"..Player.UserId])
if playersInRegion3["ID"..Player.UserId] == nil then --checking if player is not in the table
print(Player.Name.." is not in region3")
StopEvent:FireClient(Player)
end
print(playersInRegion3)
playersInRegion3 = {} --resetting the table after every loop
end
end
I tried doing this and playersInRegion3[“ID”…Player.UserId] returns as nil. For some reason this made both events fire. I appended the ID onto that because I believe if it was just the userId it would try to find the item at that index.
So I tested this, and this does not work, but table.Find does.
Here’s my testing code so you can replicate.
local Thing = {} Thing[#Thing+1] = "Hello" print(table.find(Thing,"Hello")) --This works
local Thing = {} Thing[#Thing+1] = "Hello" print(Thing("Hello")) --This does not
the first prints “1”, which is the position within the table.
The other prints nil.
Use table.Find:
if not table.Find(playersInRegion3["ID"..plr.UserId] then
--Do stuff
end
local PlayEvent = game.ReplicatedStorage:FindFirstChild('MusicEvent') --Defining events
local StopEvent = game.ReplicatedStorage:FindFirstChild('StopEvent')
-- The values for the region3
local Zone = game.Workspace.MusicZones.Zone1
local min = Vector3.new(Zone.Position.X-Zone.Size.X/2, Zone.Position.Y-Zone.Size.Y/2, Zone.Position.Z-Zone.Size.Z/2)
local max= Vector3.new(Zone.Position.X+Zone.Size.X/2, Zone.Position.Y+Zone.Size.Y/2, Zone.Position.Z+Zone.Size.Z/2)
local region = Region3.new(min,max)
-- This was the iteration function I used before. I'm not currently using it but it's here for reference
local function Contains(Table, Value)
for i, v in pairs(Table) do
if v.Name == Value.Name then
return true
end
end
end
-- Main loop
while wait(0.5) do
local min = Zone.Position - Zone.Size*.5 -- Getting the size of the zone
local max = Zone.Position + Zone.Size*.5 -- Getting the size of the zone
local partInRegion = workspace:FindPartsInRegion3(region, nil, math.huge) --Find the parts
local playersInRegion3 = {}
for _, part in pairs(partInRegion) do
if part.Name == "HumanoidRootPart" and part.Parent:FindFirstChild("Humanoid") then
local plr = game.Players:GetPlayerFromCharacter(part.Parent)
if not table.find(playersInRegion3,"ID"..plr.UserId) then
PlayEvent:FireClient(plr,Zone.Music)
end
playersInRegion3[#playersInRegion3 + 1] = "ID"..plr.UserId --putting the player in the table
end
end
for _, Player in pairs(game.Players:GetChildren()) do
print(table.find(playersInRegion3,"ID"..Player.UserId))
if table.find(playersInRegion3,"ID"..Player.UserId) == nil then --checking if player is not in the table
print(Player.Name.." is not in region3")
StopEvent:FireClient(Player)
end
print(playersInRegion3)
playersInRegion3 = {} --resetting the table after every loop
end
end
Revised the code. Once again this works, but only when one client is involved. Whenever I try it with multiple clients I get strange results where both players’ UserIds are on the table but only the first client functions correctly. The second client receives both events simultaneously which cancels out the effect.
Now that I look at that it’s completely unnecessary to have that in the code, the same thing is done right above it! I expected it to break the program but it works like a charm. Thanks for the help bro.
Here is the final code if anybody wanted to reference this. I’m using it to play/ stop ambient sound effects in the region3. All you need to get it to work is just hook up some local scripts to the events and it should work perfectly.
local PlayEvent = game.ReplicatedStorage:FindFirstChild('MusicEvent') --Defining events
local StopEvent = game.ReplicatedStorage:FindFirstChild('StopEvent')
-- The values for the region3
local Zone = game.Workspace.MusicZones.Zone1
local min = Vector3.new(Zone.Position.X-Zone.Size.X/2, Zone.Position.Y-Zone.Size.Y/2, Zone.Position.Z-Zone.Size.Z/2)
local max= Vector3.new(Zone.Position.X+Zone.Size.X/2, Zone.Position.Y+Zone.Size.Y/2, Zone.Position.Z+Zone.Size.Z/2)
local region = Region3.new(min,max)
-- This was the iteration function I used before. I'm not currently using it but it's here for reference
local function Contains(Table, Value)
for i, v in pairs(Table) do
if v.Name == Value.Name then
return true
end
end
end
-- Main loop
while wait(0.5) do
local min = Zone.Position - Zone.Size*.5 -- Getting the size of the zone
local max = Zone.Position + Zone.Size*.5 -- Getting the size of the zone
local partInRegion = workspace:FindPartsInRegion3(region, nil, math.huge) --Find the parts
local playersInRegion3 = {}
for _, part in pairs(partInRegion) do
if part.Name == "HumanoidRootPart" and part.Parent:FindFirstChild("Humanoid") then
local plr = game.Players:GetPlayerFromCharacter(part.Parent)
if not table.find(playersInRegion3,"ID"..plr.UserId) then
PlayEvent:FireClient(plr,Zone.Music)
end
playersInRegion3[#playersInRegion3 + 1] = "ID"..plr.UserId --putting the player in the table
end
end
for _, Player in pairs(game.Players:GetChildren()) do
print(table.find(playersInRegion3,"ID"..Player.UserId))
if table.find(playersInRegion3,"ID"..Player.UserId) == nil then --checking if player is not in the table
print(Player.Name.." is not in region3")
StopEvent:FireClient(Player)
end
print(playersInRegion3)
--playersInRegion3 = {} --resetting the table after every loop
end
end