My game has a music zones script that seems to randomly cause massive lag spikes on the server side, making my game basically unplayable.
This is the code, does anybody have any tips on how I could optimize it?
(I originally took part of the code from another DevForum post about music zones)
local musicZones = {
{workspace.MusicZones.TokensMusicZone, "rbxassetid://1840313516"},
{workspace.MusicZones.ClothesMusicZone, "rbxassetid://1844487326"},
{workspace.MusicZones.PoliceMusicZone, "rbxassetid://1839318061"},
{workspace.MusicZones.TrainStationZone, "rbxassetid://0"},
{workspace.MusicZones.CafeMusicZone, "rbxassetid://16755115716", 5},
}
local inPart = {}
local possiblePlayers = {}
local players = game:GetService('Players')
function check(v)
possiblePlayers[v[1].Name] = {}
local parts = workspace:GetPartsInPart(v[1])
for _, part in parts do
local player = players:GetPlayerFromCharacter(part.Parent)
if player and not table.find( possiblePlayers[v[1].Name], player) then
table.insert( possiblePlayers[v[1].Name], player)
end
end
for _, player in possiblePlayers[v[1].Name] do
if not table.find(inPart[v[1].Name], player) then
if v[1].Name == "TrainStationZone" then
game.ReplicatedStorage.Events.TrainAmbience:FireClient(player, true)
else
local volume = v[3]
if not v[3] then
volume = 0.5
end
game.ReplicatedStorage.Events.UpdateMusic:FireClient(player, v[2], volume)
end
end
end
for _, player in inPart[v[1].Name] do
if not table.find( possiblePlayers[v[1].Name], player) then
if v[1].Name == "TrainStationZone" then
game.ReplicatedStorage.Events.TrainAmbience:FireClient(player, false)
else
game.ReplicatedStorage.Events.UpdateMusic:FireClient(player, 0, 0.5)
end
end
end
inPart[v[1].Name] = possiblePlayers[v[1].Name]
end
for i,v:BasePart in pairs(musicZones) do
inPart[v[1].Name] = {}
possiblePlayers[v[1].Name] = {}
v[1].Touched:Connect(function()
check(v)
end)
v[1].TouchEnded:Connect(function()
check(v)
end)
end
I would have a table of Parts and another table of Sounds, with indexes respective to the first table, and a variable for the current music. When a part is touched, stop any music that’s playing, play the sound corresponding to the part, and update the current music. Have another event that detects when the current music ends where it restarts.
The problem probably arises from the fact that your GetPartsInPart function is returning a whole map load of parts and you’re looping through a lot of parts every time it’s touched (which means multiply by 7 for R6 rigs (without accessories) or 16 for R15 Rigs (without accessories).
It’s been ages, but I’m pretty sure my solution from here still works.
Though rather than using Region3 I’d use this function I have saved around since it’s way cleaner and easier to use.
local function isInsideBrick(position: Vector3, brick: BasePart)
local v3 = brick.CFrame:PointToObjectSpace(position);
return (math.abs(v3.X) <= brick.Size.X / 2)
and (math.abs(v3.Y) <= brick.Size.Y / 2)
and (math.abs(v3.Z) <= brick.Size.Z / 2);
end
Thanks for the input everybody!
This is the solution I settled on for now, might update it later to have better checks for if a player is in the brick.
local Players = game:GetService('Players')
local musicZones = {
{workspace.Map.MusicZones.TokensMusicZone, "rbxassetid://1840313516"},
{workspace.Map.MusicZones.ClothesMusicZone, "rbxassetid://1844487326"},
{workspace.Map.MusicZones.PoliceMusicZone, "rbxassetid://1839318061"},
{workspace.Map.MusicZones.TrainStationZone, "rbxassetid://0"},
{workspace.Map.MusicZones.CafeMusicZone, "rbxassetid://16755115716", 5},
}
local inPart = {}
for i,v:BasePart in pairs(musicZones) do
inPart[v[1].Name] = {}
v[1].Touched:Connect(function(hit:BasePart)
local char = hit:FindFirstAncestorOfClass("Model")
if not char or table.find(inPart[v[1].Name], char.Name) or hit.Name ~= "HumanoidRootPart" then
return
end
if char then
local plr = Players:GetPlayerFromCharacter(char)
if plr then
table.insert(inPart[v[1].Name], plr.Name)
if v[1].Name == "TrainStationZone" then
game.ReplicatedStorage.Events.TrainAmbience:FireClient(plr, true)
else
game.ReplicatedStorage.Events.UpdateMusic:FireClient(plr, v[2], 0.5)
end
else
return
end
end
end)
v[1].TouchEnded:Connect(function(hit)
local char = hit:FindFirstAncestorOfClass("Model")
if not char or not table.find(inPart[v[1].Name], char.Name) or hit.Name ~= "HumanoidRootPart" then
return
end
if char then
local plr = Players:GetPlayerFromCharacter(char)
if plr then
table.remove(inPart[v[1].Name], table.find(inPart[v[1].Name], plr.Name))
if v[1].Name == "TrainStationZone" then
game.ReplicatedStorage.Events.TrainAmbience:FireClient(plr, true)
else
game.ReplicatedStorage.Events.UpdateMusic:FireClient(plr, 0, 0.5)
end
else
return
end
end
end)
end