ents.FindInSphere() and util.TraceLine() reducing costness.
35 replies, posted
snipped
ents.FindInSphere() is the fastest by far, as it a C function. Also what are you using this for?
[QUOTE=CmdrMatthew;26714975]ents.FindInSphere() is the fastest by far, as it a C function. Also what are you using this for?[/QUOTE]To get entities inside a certain radius every 0.015 seconds.
Why would you ever need to do it that often?
[QUOTE=CmdrMatthew;26715215]Why would you ever need to do it that often?[/QUOTE]I need it to run atleast every 0.1 seconds, normal think speed (0.015) gives much greater results, its necessary to run it that often for what I'm currently doing. And it is also ran multiple times (depending on how many players there currently are and a few other variables), add the trace and we got some serious recourse management problems :/ Which is why I made this thread.
Could you please tell us exactly what you are using this for? Its hard to give suggestions when you don't know what the person it using it for.
I'm using it for multiple scripts, made it as officiant as possible, not running it unless completely necessary.
An example: Running a trace from an npc to a player, then checking for entity's in lets say 1000 units at traces impact position.[LUA]hook.Add("Think", "Example", function()
if Enabled and (Enabled_Delay and CurTime() >= Enabled_Delay or !Enabled_Delay) then
for _, ply in pairs(player.GetAll()) do
for _, npc in pairs(ents.FindInSphere(ply:GetPos(), 100000)) do
ply.ATable = ents.FindInSphere(util.TraceLine({start = npc:EyePos(), endpos = ply:GetPos(), filter = ply}).HitPos, 1000))
end
end
Enabled_Delay = CurTime()+0.1
end
end)[/LUA]Basically thats the core of one of the scripts.
You could try to use Vector:LenghtSqr, it returns the lenght of the vector without the square root, and then compare the lenght with x^2 + y^2 + z^2 (assuming that x, y and z are the components of your vector). But yet I have no idea if it is more efficient than using ents.FindInSphere
Thanks, Ill try that. But are there any alternatives to a util.TraceLine()? Cause thats the main thing thats the main thing consuming all the recourses.
I don't think, but are you using the trace for what?
for the first find in sphere, wouldn't it be better to use findbyclass("npc_*")?
[QUOTE=-TB-;26717403]for the first find in sphere, wouldn't it be better to use findbyclass("npc_*")?[/QUOTE]No, since there are plenty of SNPC's with different class name for example: "monster_*", npc could use any class name :/
That was just an example, not a part of the script, in the script I just check with Entity:IsNPC().
[editline]16th December 2010[/editline]
[QUOTE=Loures;26717178]I don't think, but are you using the trace for what?[/QUOTE]To get a hit position from npc:EyePos() to ply:GetPos().
What is the code going to be used for? I mean like what are you actually using it for.
[QUOTE=CmdrMatthew;26723245]What is the code going to be used for? I mean like what are you actually using it for.[/QUOTE]Why are you so obsesed with getting my code? I told you the basics of one of the scripts, and I'm searching for their alternatives, other code is irrelevant to this discussion.
[QUOTE=freemmaann;26726655]Why are you so obsesed with getting my code? I told you the basics of one of the scripts, and I'm searching for their alternatives, other code is irrelevant to this discussion.[/QUOTE]
don't rate people who are trying to help you dumb
[QUOTE=freemmaann;26717627]No, since there are plenty of SNPC's with different class name for example: "monster_*", npc could use any class name :/
That was just an example, not a part of the script, in the script I just check with Entity:IsNPC().
[editline]16th December 2010[/editline]
To get a hit position from npc:EyePos() to ply:GetPos().[/QUOTE]
Then you have no chances other than using traces, you could calculate a less computationally expensive one by doing some vector math but I'm not sure about that.
Here's a slightly optimized version of your code.
[lua]local lastNpc
local trcTable = {}
hook.Add("Think", "Example", function()
if Enabled and (Enabled_Delay and CurTime() >= Enabled_Delay or !Enabled_Delay) then
for _, ply in pairs(player.GetAll()) do
lastNpc = ents.FindInSphere(ply:GetPos(), 100000)
lastNpc = lastNpc[#lastNpc]
trcTable.start = lastNpc:EyePos()
trcTable.endpos = ply:GetPos()
trcTable.filter = ply
ply.ATable = ents.FindInSphere(util.TraceLine(trcTable).HitPos, 1000))
end
Enabled_Delay = CurTime()+0.1
end
end)[/lua]
[QUOTE=raBBish;26731416]Here's a slightly optimized version of your code.
[lua]local lastNpc
local trcTable = {}
hook.Add("Think", "Example", function()
if Enabled and (Enabled_Delay and CurTime() >= Enabled_Delay or !Enabled_Delay) then
for _, ply in pairs(player.GetAll()) do
lastNpc = ents.FindInSphere(ply:GetPos(), 100000)
lastNpc = lastNpc[#lastNpc]
trcTable.start = lastNpc:EyePos()
trcTable.endpos = ply:GetPos()
trcTable.filter = ply
ply.ATable = ents.FindInSphere(util.TraceLine(trcTable).HitPos, 1000))
end
Enabled_Delay = CurTime()+0.1
end
end)[/lua][/QUOTE]Thanks, but how exactly does it optimize it? :/
[editline]16th December 2010[/editline]
[QUOTE=Loures;26731288]Then you have no chances other than using traces, you could calculate a less computationally expensive one by doing some vector math but I'm not sure about that.[/QUOTE]Anything less expensive would be awesome. Is it possible to do something with the vector math not doing a trace? :/ I mean it still has to know the hit position, right?
[QUOTE=freemmaann;26731543]Thanks, but how exactly does it optimize it? :/[/QUOTE]
Variables declared outside the loop, declaring locals (especially tables) add up quickly and when the GC comes, it causes spikes.
Reduced looping. Your old code was looping through ents.FindInSphere and setting ply.ATable every time, which is the same as setting it once to with the last entity of the list.
Forget what I said, vector math is useless in this case.
[QUOTE=raBBish;26731673]Variables declared outside the loop, declaring locals (especially tables) add up quickly and when the GC comes, it causes spikes.
Reduced looping. Your old code was looping through ents.FindInSphere and setting ply.ATable every time, which is the same as setting it once to with the last entity of the list.[/QUOTE]Thanks, I'll integrate something like this in the script.
[editline]16th December 2010[/editline]
[QUOTE=Loures;26731728]Forget what I said, vector math is useless in this case.[/QUOTE]Oh :/ ok.
Consider the LenghtSqr way of doing stuff anyway
[lua]
for _, ent in pairs(ents.FindByClass("npc_*")) do
if ent:GetPos():LenghtSqr() <= 1000 then
--dostuff
end
end
[/lua]
[QUOTE=freemmaann;26726655]Why are you so obsesed with getting my code? I told you the basics of one of the scripts, and I'm searching for their alternatives, other code is irrelevant to this discussion.[/QUOTE]
I don't want your code at all. I just want to help you find alternatives, which I can't do if I don't know what you are aiming to do with your code. Just one simple sentence "I am trying to....." or "I am....".
[QUOTE=Loures;26731796]Consider the LenghtSqr way of doing stuff anyway
[lua]
for _, ent in pairs(ents.FindByClass("npc_*")) do
if ent:GetPos():LenghtSqr() <= 1000 then
--dostuff
end
end
[/lua][/QUOTE]Wouldn't the LenghtSqr need a second vector?
[QUOTE=freemmaann;26732028]Wouldn't the LenghtSqr need a second vector?[/QUOTE]
Length/LengthSqr returns distance from origin, (0,0,0). For the distance from some other vector, you'd use this.
[lua](vec1-vec2):LengthSqr()[/lua]
[QUOTE=CmdrMatthew;26732022]I don't want your code at all. I just want to help you find alternatives, which I can't do if I don't know what you are aiming to do with your code. Just one simple sentence "I am trying to....." or "I am....".[/QUOTE]Ok. I am trying[QUOTE=freemmaann;26715007]To get entities inside a certain radius every 0.015 seconds.[/QUOTE]Thats one of the things that I'm trying to do. And I don't know what else I can tell you I mean I even wrote the basics what I'm trying to do..
[QUOTE=freemmaann;26732062]Thats one of the things that I'm trying to do. And I don't know what else I can tell you I mean I even wrote the basics what I'm trying to do..[/QUOTE]
I can't think of a reason you'd need to get a list of entities in a radius every Think.
[QUOTE=raBBish;26732043]Length/LengthSqr returns distance from origin, (0,0,0). For the distance from some other vector, you'd use this.
[lua](vec1-vec2):LengthSqr()[/lua][/QUOTE]Oh, thanks.
For learning purposes:
Lenght is the same as doing
[lua] math.sqrt(x^2 + y^2 + z^2) [/lua]
LenghtSqr does
[lua] x^2 + y^2 + z^2 [/lua]
For comparisions, LenghtSqr is better as it is less computationally expensive.
[QUOTE=raBBish;26732076]I can't think of a reason you'd need to get a list of entities in a radius every Think.[/QUOTE]There could be many reasons.. Like searching every child of an entity in a radius, or checking if there are entitys of the same type around it. I would use: ents.GetAll() then use the LengthSqr(), but ents.FindInSphere() Finds the closest part of an entity not its center, which is useful.
[editline]16th December 2010[/editline]
[QUOTE=Loures;26732095]For learning purposes:
Lenght is the same as doing
[lua] math.sqrt(x^2 + y^2 + z^2) [/lua]
LenghtSqr does
[lua] x^2 + y^2 + z^2 [/lua]
For comparisions, LenghtSqr is better as it is less computationally expensive.[/QUOTE]Thanks, gonna use that instead of Vector:Distance(Vector) from now on.
Sorry, you need to Log In to post a reply to this thread.