Speaking from personal experience: Regions are always laggy on Roblox. I would note the center positions of regions and do magnitude comparisons constantly, maybe using heartbeat.
(TorsoPosition - RegionPosition).Magnitude will give you the distance between a region’s center and the player. Do a comparison to know if the player is in or not.
You can check multiple part magnitudes to know how much of the player is inside, it will still be much better performance-wise. It will indeed make a sphere but I don’t think that is an issue.
Absolutely, just stating in case someone else stumbles upon this and their use relies on a cube, for example playing sound only in a cuboid room, or where the region is significantly longer than it is wide or tall (for example different floors in a building)
A sphere will not cover a rectangular area, i’m trying to limit the amount of outdoor regions i do have, so i think square is better. I’ve been trying to use heartbeat and render stepped, but both create lag. Looping through all the regions in a place like what i’m working with.
I also dont wana use blocks, with a touched event, because first its unreliable, and second i have projectiles that it will effect, even with a hit ignore thing, its still far more blocks than i want. Plus blocks cant cover the radius i want to cover.
Heartbeat shouldn’t have as much of an impact. Have you tried performing a different check on each event? For example, if you have 4 regions, you could do one per Heartbeat, therefore doing each region only once per 4 Hearbeats.
If your number of regions is going to be a lot higher, then you might want to do something else, but provided the number is low:
local regionIndex = 0
game:GetService( 'RunService' ).Heartbeat:Connect( function ()
regionIndex = regionIndex % #SoundRegions + 1
-- DO YOUR CHECK ON SoundRegions[ regionIndex ] HERE
end )
This will help spread the load out, as you’ll be taking 1/4 of the time per heartbeat than you currently are.
This part will take it back to 1 after reaching the number of SoundRegions. You don’t have to do anything other than put your code in there, and instead of a for loop running through all the regions, you just use the one region SoundRegions[ regionIndex ]
% is the modulo operator and essentiall a % n gives you the remainder after n is taken away from a as many times as possible. 5 % 3 = 2. 100 % 30 = 10. 20 % 10 = 0.
For some odd reason it wont index the regionIndex in the sound regions with SoundRegion[regionIndex]. Im very familiar with tables so i must be doing something dumb. i’m even printing, and its coming out nil.
My mistake - didn’t realise the table was a dictionary. Slightly harder with a dictionary so if I were you I’d change it to something like this:
-- YOUR EXISTING REGIONS SETUP
local SoundRegions = {
{ Bouldaron, "City" },
{ Namaramore, "City" },
{ Wilderness, "Nature" },
{ Wilderness2, "Nature" },
}
local RegionSound = Instance.new("Sound")
RegionSound.Name = "Region_Sound"
RegionSound.Parent = workspace
RegionSound.Looped = true
RegionSound.Volume = .3
local regionIndex = 0
game:GetService( 'RunService' ).Heartbeat:Connect( function ()
regionIndex = regionIndex % #SoundRegions + 1
local region = SoundRegions[ regionIndex ][ 1 ]
local ST = SoundRegions[ regionIndex ][ 2 ]
for partname, part in pairs(workspace:FindPartsInRegion3WithWhiteList(region, {Player.Character}, 10)) do
if part.Parent:FindFirstChild("Humanoid") and part.Parent.Name == Player.Name then
if RegionSound.SoundId ~= "rbxassetid://"..Sounds[ST] then
RegionSound:Stop()
print(ST, "Is the sound of the thing you are in")
RegionSound.SoundId = "rbxassetid://"..Sounds[ST]
RegionSound:Play()
end
end
end
end
end )
Okay, this is how i’ve been indexing the regions when the game starts:
for _,region in pairs(RegionMarkers:GetChildren()) do
local Point1 = region:WaitForChild("RegionMarker1").Position
local Point2 = region:WaitForChild("RegionMarker2").Position
local region3 = Region3.new(
Vector3.new(math.min(Point1.X, Point2.X), math.min(Point1.Y, Point2.Y), math.min(Point1.Z, Point2.Z)),
Vector3.new(math.max(Point1.X, Point2.X), math.max(Point1.Y, Point2.Y), math.max(Point1.Z, Point2.Z))
)
SoundRegions[region.Name] = region3
print(region.Name,SoundRegions[region.Name])
end
So i put regions in the dictionary after the game starts.
I GOT IT WORKING YAY. thanks very much. But one follow up question. Is there a way to make it skip even more heartbeats? And if so, will that help reduce even more lag? In my project i don’t need the sound to happen instantaneously on the button as soon as you leave the region.
local POLL_THRESHOLD = 10
local regionIndex = 0
local pollCount = 0
game:GetService( 'RunService' ).Heartbeat:Connect( function ()
pollCount = pollCount + 1
if pollCount < POLL_THRESHOLD then
return
end
pollCount = 0
regionIndex = regionIndex % #SoundRegions + 1
-- rest of code here
Essentially waits for a specified number of heartbeats before incrementing and doing the next region. In this case, 10, which is roughly 1/6th of a second break on the client. Increase the number to make it take longer. 60 will be roughly 1 second pause between each region check.