I have this code run whenever the player respawns and preferably, I’d like to have a similar very responsive and quick effect that while wait() do has but obviously not using a loop. There’s many ways to go about this, but what solution would have the least proformance impact and still achive the quick responsive effect that a while loop has?
local lastZone
while wait() do --TODO: Make this not a loop
for i, zone in pairs(ReplicatedStorage.LocationRegions:GetChildren()) do
for x, hitbox in pairs(zone:GetChildren()) do
local min = hitbox.Position - hitbox.Size * 0.5
local max = hitbox.Position + hitbox.Size * 0.5
local partsFound = workspace:FindPartsInRegion3WithWhiteList(Region3.new(min, max), game.Players.LocalPlayer.Character:GetDescendants(), 100)
for y, part in pairs(partsFound) do
if part.Name == "HumanoidRootPart" and lastZone ~= zone then
lastZone = zone
updateLocation(zone.Name)
end
end
end
end
end
You can try recursive functions, essentially you’d call the function inside of itself near the end.
local function loop()
--you code here--
loop() --run forever
end
loop() --initially call it
Unlike while loops, such functions don’t require waits in most cases. They’re only required when you are executing something big like generating a whole map of procedural terrain.
It checks the player’s location to see what area of my map they are in and whenever it changes, it fires the updateLocation() function which displays their new location.
That seems like a recipe for a stack overflow. Use an event based system.
local lastZone
local function check()
local min, max, partsFound -- basic optimization strategy, define variables outside loops
for i, zone in pairs(ReplicatedStorage.LocationRegions:GetChildren()) do
if lastZone ~= zone then
for x, hitbox in pairs(zone:GetChildren()) do
min = hitbox.Position - hitbox.Size * 0.5
max = hitbox.Position + hitbox.Size * 0.5
partsFound = workspace:FindPartsInRegion3WithWhiteList(Region3.new(min, max), game.Players.LocalPlayer.Character:GetDescendants(), 100)
for y, part in pairs(partsFound) do
if part.Name == "HumanoidRootPart" then
lastZone = zone
updateLocation(zone.Name)
return -- no need to continue after the zone is found?
end
end
end
end
end
end
game:GetService("RunService").RenderStepped:Connect(check)
One quick revision that would improve preformance:
I noticed that I check if the last zone isn’t current zone when it could be done earlier to avoid doing any raycasting if the player is still in the same area as before.
local lastZone
while wait() do --TODO: Make this not a loop
for i, zone in pairs(ReplicatedStorage.LocationRegions:GetChildren()) do
if lastZone ~= zone then
for x, hitbox in pairs(zone:GetChildren()) do
local min = hitbox.Position - hitbox.Size * 0.5
local max = hitbox.Position + hitbox.Size * 0.5
local partsFound = workspace:FindPartsInRegion3WithWhiteList(Region3.new(min, max), game.Players.LocalPlayer.Character:GetDescendants(), 100)
for y, part in pairs(partsFound) do
if part.Name == "HumanoidRootPart" then
lastZone = zone
updateLocation(zone.Name)
end
end
end
end
end
end