Soo i want to ask simple question, how do i optimize distance checks for tower defense game? We plan to make game run with few hundred enemies and tens of towers placed, but to accomplish this we need to know how to optimize distance checks
for now it looks like this:
for i, enemy in enemies do
if (enemy.Position - tower.Position).Magnitude <= distance then
-- code
end
end
One of the simplest ways to optimise a distance check is to store the position of any stationary objects in a variable, so you don’t access the position using OBJECT.Position each time. (So in this case, store the tower position)
A really simple optimization is to use pure math rather than Vector3 object stuff
Here’s the math for a distance check (change a and b to the positions)
Kinda, but if you catch yourself writing thing.Position a lot, its better to do local pos = thing.Position and just use pos from there. This is a generally good practice anyway
To be clear, everytime you do thing.Position it has to search thing for Position, although it is pretty fast, it still can make a difference
hmm i would rather consider this micro optimization, the problem is let’s say we have 400 enemies, i need to check 10 times per second for those 400 enemies, soo we perform magnitude checks almost 48000 for 120 towers soo 480000 checks per second, of course magnitude check will be disabled when target was… targetted? and changed to single enemy rather than 400, but still it’s a lot of lag, this is my main problem
Here is a list of potential ways to make it run faster
Use the “native codegen” feature (only works on server). What this does is it compiles your code to make it run faster. It works best with math-heavy code
“In order to enable native code generation you need to put the --!native directive on top of your script.”
Try to use as much pure math as possible and minimize using Vector3 operations (Vector3 + Vector3, etc.)
Try to use a chunking system like @Pokemoncraft5290 mentioned, which speeds up things like distance checks. (Check out what they sent, but you might have to modify it)
Generally try not to repeat things, use what I said in an earlier reply as an example
Optimizing past simple things can be time consuming and stressful, I suggest you test the waters first and only put much effort into it if you see it causing issues.
I won’t help you past here, but pretty much any response I would give you would probably just be a search here on the devforum
Experimentally, I’m finding anything that isn’t flat-squared-distance to be slower than Vector3.Magnitude.
N = 10e6
local t0 = tick()
for i = 1, N do
local p1 = Vector3.new(math.random(), math.random(), math.random())
local p2 = Vector3.new(math.random(), math.random(), math.random())
end
print("Tare:",tick() - t0)
tare = tick() - t0
local t0 = tick()
for i = 1, N do
local p1 = Vector3.new(math.random(), math.random(), math.random())
local p2 = Vector3.new(math.random(), math.random(), math.random())
local m = (p1 - p2).Magnitude
end
print("Vector3 magnitude (minus tare):", tick() - t0 - tare)
local t0 = tick()
for i = 1, N do
local p1 = Vector3.new(math.random(), math.random(), math.random())
local p2 = Vector3.new(math.random(), math.random(), math.random())
local m = math.sqrt((p1.X - p2.X)^2 + (p1.Y - p2.Y)^2 + (p1.Z - p2.Z)^2)
end
print("Magnitude (minus tare):", tick() - t0 - tare)
local t0 = tick()
for i = 1, N do
local p1 = Vector3.new(math.random(), math.random(), math.random())
local p2 = Vector3.new(math.random(), math.random(), math.random())
local mSq = (p1.X - p2.X)^2 + (p1.Y - p2.Y)^2 + (p1.Z - p2.Z)^2
end
print("Squared magnitude (minus tare):", tick() - t0 - tare)
local t0 = tick()
for i = 1, N do
local p1 = Vector3.new(math.random(), math.random(), math.random())
local p2 = Vector3.new(math.random(), math.random(), math.random())
local mSqFlat = (p1.X - p2.X)^2 + (p1.Z - p2.Z)^2
end
print("Squared flat magnitude (minus tare):", tick() - t0 - tare)
Doing some tests I found that most of the time spent on the manual method is simply just the indexing of the Vector3
--!strict
local ta = {}
local tb = {}
--generate some random vectors
for count = 1, 1000 do
ta[count] = Vector3.new(math.random(), math.random(), math.random())
tb[count] = Vector3.new(math.random(), math.random(), math.random())
end
wait(2)
local start = os.clock()
for count = 1, 1000 do
local a, b = ta[count], tb[count]
local magnitude = (a - b).Magnitude
end
print(os.clock() - start)
local start = os.clock()
for count = 1, 1000 do
local a, b = ta[count], tb[count]
--The most expensive part here
local e = a.X
local e = b.X
local e = a.Y
local e = b.Y
local e = a.Z
local e = b.Z
end
print(os.clock() - start)