• Optimizing Scripted Entities
    5 replies, posted
I'm pretty new to lua scripting and making things in Garry's Mod and i've made two entities that work as health and armor chargers. The problem with these entities is that when you have more than one of them it makes your frame rate drop pretty significantly. My question is what might be causing these issues and how would I go about fixing the issues with frame rate. Any help is worth a lot, thank you. --[[--------------------------------------------------------------------------- cl_unit.lua ---------------------------------------------------------------------------]] include("shared.lua") function ENT:Initialize() end surface.CreateFont( "HudFont", {   font = "Arial", -- Use the font-name which is shown to you by your operating system Font Viewer, not the file name   extended = false,   size = 100,   weight = 700,   blursize = 0,   scanlines = 0,   antialias = true,   underline = false,   italic = false,   strikeout = false,   symbol = false,   rotary = false,   shadow = false,   additive = false,   outline = false, }) function draw.Circle(x, y, radius, sAng, eAng)     local cir = {}     table.insert( cir, { x = x, y = y, u = 0.5, v = 0.5 } )     for i = sAng, eAng, 0.1 do       local a = math.rad( i )       table.insert( cir, { x = x + math.sin( a ) * radius, y = y + math.cos( a ) * radius } )     end     surface.DrawPoly( cir ) end function ENT:Draw()     self:DrawModel()     local Pos = self:GetPos()     local Ang = self:GetAngles()     local cAng = Ang     local hp_stored = self:Gethp_stored()     local percent = (hp_stored / 1000) * 100     local owner = self:Getowning_ent()     owner = (IsValid(owner) and string.sub(owner:Nick(), 0, 8)) or DarkRP.getPhrase("unknown")     surface.SetFont("HudFont")     local TextWidth1 = surface.GetTextSize(owner)     local TextWidth2 = surface.GetTextSize(percent .. "%")     Ang:RotateAroundAxis(Ang:Up(), 90)     Ang:RotateAroundAxis(cAng:Forward(), 180)     --[[------------------------------------------           Health Station General Skinning     --]]------------------------------------------     cam.Start3D2D(Pos + (Ang:Up() * -7.9), Ang, 0.05)       surface.SetDrawColor(30,30,30,255)       draw.NoTexture()       surface.DrawRect(-222,-150,444,370)     cam.End3D2D()     cam.Start3D2D(Pos + (Ang:Up() * -0.2), Ang, 0.05)       surface.SetDrawColor(30,30,30,255)       draw.NoTexture()       surface.DrawRect(-222,-150,444,370)     cam.End3D2D()     Ang:RotateAroundAxis(Ang:Right(),90)     cam.Start3D2D(Pos + (Ang:Up() * 11.1), Ang, 0.05)       surface.SetDrawColor(30,30,30,255)       draw.NoTexture()       surface.DrawRect(-160,-150,158,370)     cam.End3D2D()     cam.Start3D2D(Pos + (Ang:Up() * -11.1), Ang, 0.05)       surface.SetDrawColor(30,30,30,255)       draw.NoTexture()       surface.DrawRect(-160,-150,158,370)     cam.End3D2D()     Ang:RotateAroundAxis(Ang:Forward(),90)     cam.Start3D2D(Pos + (Ang:Up() * 11), Ang, 0.05)       surface.SetDrawColor(30,30,30,255)       draw.NoTexture()       surface.DrawRect(-160,-222,158,444)     cam.End3D2D()     cam.Start3D2D(Pos + (Ang:Up() * -10.2), Ang, 0.05)       surface.SetDrawColor(30,30,30,255)       draw.NoTexture()       surface.DrawRect(-160,-222,158,444)     cam.End3D2D()     Ang:RotateAroundAxis(Ang:Up(),-270)     Ang:RotateAroundAxis(Ang:Right(),-180)     cam.Start3D2D(Pos + (Ang:Up() * 10.2) + (Ang:Forward() * -1) + (Ang:Right() * -7.5), Ang, 0.05)       draw.WordBox(10, -TextWidth1 * 0.5, 0, owner, "HudFont", Color(140, 0, 0, 0), Color(200, 200, 200, 255))     cam.End3D2D()     Ang:RotateAroundAxis(Ang:Right(),180)     Ang:RotateAroundAxis(Ang:Up(),270)     ---------------------------------------------     Ang:RotateAroundAxis(Ang:Forward(),-90)     --[[-----------------------------------------           Health Station Information Panel     --]]-----------------------------------------     Ang:RotateAroundAxis(Ang:Right(),-90)     cam.Start3D2D(Pos + (cAng:Up() * -8.3 ) + (cAng:Forward() * -30) + (cAng:Right() * 2), Ang, 0.05)     if hp_stored != 0 then         surface.SetDrawColor(200, 50, 50, 250)         draw.NoTexture()         draw.Circle(600, 0, 160, 360, hp_stored * 0.3601 + 360)     end         surface.SetDrawColor(255, 255, 255, 255)         draw.NoTexture()         draw.Circle(600, 0, 130, 0, 361)         surface.SetDrawColor(35, 35, 35, 255)         draw.NoTexture()         draw.Circle(600, 0, 125, 0, 361)     cam.End3D2D()     Ang:RotateAroundAxis(Ang:Forward(),180)     cam.Start3D2D(Pos + (Ang:Forward() * -0.5) + (Ang:Up() * 8.5), Ang, 0.05)         draw.WordBox(10, -TextWidth2 * 0.5, -95, percent .. "%", "HudFont", Color(140, 0, 0, 0), Color(255, 255, 255, 255))     cam.End3D2D() end function ENT:Think() end --[[--------------------------------------------------------------------------- init.lua ---------------------------------------------------------------------------]] AddCSLuaFile("cl_init.lua") AddCSLuaFile("shared.lua") include("shared.lua") function ENT:Initialize()     self:SetModel("models/props_c17/consolebox03a.mdl")     self:PhysicsInit(SOLID_VPHYSICS)     self:SetMoveType(MOVETYPE_VPHYSICS)     self:SetSolid(SOLID_VPHYSICS)     local phys = self:GetPhysicsObject()     phys:Wake()     self:Sethp_stored(1000)     self:SetColor( Color(255,55,55,255)) end function ENT:Use(act, call)   if isnumber(act.nextuse) == false then act.nextuse = CurTime() end   if act.nextuse < CurTime() then     if act:Health() < 100 and self:Gethp_stored() ~= 0 and self:IsPlayerHolding() == false then         act:SetHealth(act:Health() + 1)         self:Sethp_stored(self:Gethp_stored() - 1)         self:EmitSound("hl1/fvox/boop.wav", 150, act:Health() / act:GetMaxHealth() * 100, 0.7, CHAN_AUTO)     elseif self:Gethp_stored() == 0 then         self:Destroy()     end       act.nextuse = CurTime() + 0.2   end end function ENT:Destroy()   self:Remove()   self:EmitSound("physics/cardboard/cardboard_box_break2.wav",75,100,1,CHAN_AUTO) end function ENT:OnRemove()     if self.sound then         self.sound:Stop()     end end --[[--------------------------------------------------------------------------- shared.lua ---------------------------------------------------------------------------]] ENT.Type = "anim" ENT.Base = "base_gmodentity" ENT.PrintName = "Health Station" ENT.Author = "Rudolpho" ENT.Category = "Health and Armor" ENT.Editable = true ENT.Spawnable = true ENT.AdminSpawnable = true function ENT:SetupDataTables()     self:NetworkVar("Int", 0, "hp_stored")     self:NetworkVar("Entity", 0, "owning_ent") end
Well we can narrow it down to your Draw function at the very least because as far as I can tell all the other code exists in one off calls, where as the Draw func is done every frame. Without the ability to profile this code I'm just going call out what I see as red flags. Red Flag #1: function draw.Circle(x, y, radius, sAng, eAng) local cir = {} table.insert( cir, { x = x, y = y, u = 0.5, v = 0.5 } ) for i = sAng, eAng, 0.1 do local a = math.rad( i ) table.insert( cir, { x = x + math.sin( a ) * radius, y = y + math.cos( a ) * radius } ) end surface.DrawPoly( cir ) end This draw.Circle function is called 3 times in your Draw function. At least two of these draw full circles (360 degrees) and you only increment by .1 in the for loop. This means that each of these fulls circles is being draw with 3600 points, or 10 per degree, which is way way WAY more than you would ever need. This also means that you're performing 3600 * 3 math.rad, math.sin, and math.cos, functions which can really start to add up, particularly the trig. I would changed that increment value substantially, from .1 to something much larger. Depending on the size of these circles you could probably get away with as high as 20 for your incrementer, which would result in 360/20=18 points. If that's not smooth enough go down from 20, but you shouldn't need to go any lower than say... 5 I'm willing to bet. You could also precompute this table and save it off which would remove much of the overhead in exchange for memory, but that shouldn't be necessary. Lets start with that and see where it gets us.
I changed the increment to 5 and things are running much smoother now, thanks so much for the help, it's made a massive difference.
Hey awesome man, happy to help!
Shameless plug
Looks like a really great tool from what I saw, the blurred circle could make some very interesting stuff, might use in the future, thanks for sharing.
Sorry, you need to Log In to post a reply to this thread.