Alternative Activation for Region3 other than a loop?

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.

Just be aware that this will make a sphere instead of a cube and watch out for 49% of the player being in the region and undetected.

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.

1 Like

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)

1 Like

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.

I’ll try this. However, will it reset by itself, i mean, i don’t have to reset regionIndex at anypoint? and if i do, how would you do it?

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.

Thankyou for your help and patience, i will give it a try :slight_smile:

1 Like

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 )

1 Like

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’m just trying to get straight the cleanest way of producing the dictionary so that it can run efficiently

My original problem was with the while true loop there was a weird snapping thing that would happen every time the loop restarted.

Okay, it’ll still work, you just need to add in the format shown in my snippet, so:

table.insert( SoundRegions, { region3, soundType } )

I noticed you didn’t have sound type in that last snippet, so you probably want to assign that where I’ve put the variable.

The loop will essentially update itself and start considering the new regions without having to touch the heartbeat function at all.

Yeah that snippet i just sent comes before the loop, it just finds all the markers and creates the regions, and puts the regions in the table

I GOT IT WORKING :smile: 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.

I would like to if i can keep the average pings as low as possible.

You could make it poll.

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.

1 Like

You get to be permanently instated as my personal hero! You have been so helpful thankyou so much!

1 Like