I am coding an interactive grass system for grass to move arround when a player walks into it, I am trying to optimize it as much as I can.
One of the optimizations involves checking how far all of the grass is from the camera, this is so it stops being simulated and grass very far away is destroyed or replaced with imposters.
In order to check this I determined that most efficient methods are using :GetPartsBoundsInRadius() without overlap params to be faster, and comparing the distance of all existing grass against the camera’s position using .Magnitude.
The issue is that I don’t know which one is faster, all I know is that technically the more items we need to loop through and check magnitude, the slower it will get, but I also don’t know how slower :GetPartBoundsInRadius() will be compared to.
They are fundamentally different, so it doesn’t make sense to compare them. :GetPartBoundsInRadius() checks if the part’s bounding box is touching the imaginary sphere defined by the radius. But a magnitude check will only consider the center point of the part, i.e. its position.
Yeah they are different, but you can accomplish the same thing with both if you know how to. I think more so it is a usecase and most people just use magnitude…
Magnitude is definitely faster because it’s only dealing with math. Using GetPartBoundsInRadius is a spatial query operation that does a lot of 3D stuff with special rules like OverlapParams, so it’s slower.
Also, you get the benefit of native codegen and algebra trickery for using only math (you can avoid using squareroots which is usually slow to calculate)
if pos:Dot(pos) <= radius^2 then
--is the same as
if pos.Magnitude <= radius then
--but avoids using squareroots
I am aware they both work diferently, but keep in mind performing individual checks inside lua, can actually end up being slower than a single function that runs internally, its the reason why bulkMoveTo() can be more efficient.
Also It does makes sense to compare them because internally I doubt :GetPartBoundsInRadius() is grabbing every single bounding box’s vertices and then comparing them, or something like that, so it could end up being faster than magnitude.
You seem to have dodged what I said about native codegen. You can mark your function to be compiled to assembly and have it run faster than any C API. Also, a function that runs internally can still be running tons of loops that you just can’t see.
If you think about it, that’s the only way for it to determine if a box is inside a radius. It needs to check the vertices to see if they’re within range.
That post is quite a while ago and the Luau language has evolved dramatically since. Here’s my test results as of today:
Nuh if you want to get the magnitude you actually… have to get the magnitude. Which means using Pythagorean theorem which involves squareroots. You can only avoid squareroots if you’re just comparing distances.
You can definitely test it yourself but if it means convincing you then
@native local function partsInRadius(parts: {BasePart}, r: number): {BasePart}
local t: {BasePart} = {}
local r2: number = r^2
for _, p in parts do
local pos: Vector3 = p.Position
if pos:Dot(pos) <= r2 then
table.insert(t, p)
end
end
return t
end
local parts: {BasePart} = workspace.Folder:GetChildren()
local start: number = os.clock()
print(#partsInRadius(parts, 12))
print(os.clock() - start)
local start: number = os.clock()
print(#workspace:GetPartBoundsInRadius(Vector3.zero, 12))
print(os.clock() - start)