Does heavy use of GetPartsInPart worsen server performance?

Hello.
My question is as the title says.
I am trying to use GetPartsInPart to detect parts within a specific area.
Basically, I am thinking of using a While loop, but if I use a lot (specifically, about 30 locations), will the server latency worsen and will the player lag be noticeable?
My plan to reduce lag is to use task.wait to slow down the detection cycle, but is there anything else I should keep in mind?

8 Likes

GetPartsInPart might not be the best idea in this case
i suggest Touched and TouchEnded for this

4 Likes

Those events are even more unreliable for this type of thing. I suggest the ZonePlus module.

3 Likes

We are currently using Touched events, but they are unreliable and cannot be used for anchored parts, so we are looking for an alternative solution.

3 Likes

If the shapes of the parts are simple, like a box for example, you could just do GetPartBoundsInBox(), since I’m pretty sure GetPartsInPart() requires more resources. (It has to adapt to the shape)

I think OverlapParams can help too, but if there’s still lag then I’m unsure.

2 Likes

Yes.

You are telling the Server to execute a function multiple times, if the function yields (which yes :GetPartsInPart() certainly does as it takes time for it to search for objects within another), It will overwhelm the server (if fired multiple times within a specific time period), thus causing lag.

Do this on the Client, and then use a RemoteEvent to tell the Server when to make changes when needed, if this is very important stuff that shouldn’t be in Client Control, reduce the amount of checks, otherwise you would just be slowing down the server.

2 Likes

Does this mean that simply increasing the value of “a” in while task.wait(a) do will reduce the load?

3 Likes

Personally, I have transitioned to GetPartsBoundInBox since it is faster and I made a folder called Alive where I store the characters so it only has to look there (OverlapParams)

2 Likes

Are all these parts on top of each other? I feel once you leave the loop and it’s no longer checking for that particular function should there even be a problem? Those games with hundreds of buttons on the ground don’t seem to suffer this problem either if there even is one.

2 Likes

Just dont query on the server, do it on the clients and let the server sanity check.

ZonePlus does use the spatial query api afterall, maybe more efficiently but that’ll require some testing

2 Likes

Thanks for the advice!
I am looking for some accuracy and would like to use GetPartsInPart whenever possible.

Yes. Specifically, it is used to detect trains on the tracks.

while task.wait(.5) do
	TD = workspace:GetPartsInPart(script.Parent)
	if FindPart(TD) ~= nil then
		fleet = FindPart(TD).Parent.Parent.Parent
		print(fleet.FleetNumber.Value)
	end
end

My game uses fairly heavy physics and I don’t want to add more burden on the client side.
I would like to know if reducing the loop speed as much as possible will improve performance.

2 Likes

Then you should focus on optimizing said physics, a client can handle quite a bit

Yes it would, but doing it on the client and sanity checking on the server will always be a whole lot faster.

3 Likes

I understand.
I will try this.
Thanks for the advice.

3 Likes

Gonna possibly save you big time with this one.
I had an issue in my game where large builds caused a lot of client lag. I literally started remaking certain builds with less parts and converted props into meshes to try and reduce the lag. Eventually I looked at microprofilier and realized it was because I was running a loop within a 200 radius that did getpartboundsinradius every task.wait(1) to detect nearby players. Since it was cycling through all the parts within that radius it froze the game for a bit when near large builds.

To fix this I simply used collection service to tag all players then made that tag the whitelist for the getpartsboundinradius and that fixed the lag.

So if you want to avoid any lagging issues simply tag whatever u want to detect in that radius so it avoids wasting time on unnecessary parts.

To answer your question. It depends. If you are trying to detect players only or something that theres very little of. Simply tag it with collection service and make it a whitelist with overlap params to avoid lag.

This took me a while to figure out. So hopefully I helped you avoid this issue.

3 Likes

Thanks for the reply.
I want to detect only the roof of the train, so I only want to detect the part named “roof”.

local function FindPart(part)
	for i,v in pairs(part) do
		if v.Name == "roof" then
			return v
		end
	end
	return nil
end

What kind of tags are you talking about?

2 Likes

No not like your example. It still cycles through all nearby parts until one has the name “roof” the goal is to whitelist ONLY parts that would be considered the roof by tagging them with collectionservice.

I advise you look into CollectionService its easy to use and understand! I assume you aren’t familiar with it.

2 Likes

You should be using :GetPartBoundsInBox if the part you need to find objects in is a rectangular prism/cube. It’s more performant than :GetPartsInParts. Make sure to also use OverlapParams to optimize your queries.

2 Likes

I am new to it.
I will look into it and put it into practice.

The object to be detected is an ordinary part, but the sensors used are Union.
In order to detect a train running on a winding track, a Union is used as a sensor that is lined up at equal intervals on the rail.

Hello.
I have done a lot of research on my own, and most of the examples I looked at used a for loop.
I used a while loop because I want to keep detecting parts in an area.
The script works, but apparently not with success as it works with or without tags.
What am I doing wrong?

local CS = game:GetService("CollectionService")
local tag = CS:GetTagged("roof")

local function FindPart(part)
	for i,v in pairs(part) do
		if v.Name == "roof" then
			return v
		end
	end
	return nil
end

while tag do
	task.wait(.5)
	TD = workspace:GetPartsInPart(script.Parent)
	if FindPart(TD) ~= nil then
		fleet = FindPart(TD).Parent.Parent.Parent
		print(fleet.FleetNumber.Value.."-"..fleet.C6.Body.MelodySensor.SignNum.Value)
	end
end