I have a script that's rendering many parts at a time, I'm just asking, is my math horrible at performance? I have a beefy CPU to generate this math, just wondering if there's a more efficient way to do it to have it run on weak CPU's better.
diam=34 blocks=36 plz=game.Players.LocalPlayer game:GetService("RunService").RenderStepped:connect(function() if model==nil then model=Instance.new("Model", workspace) model.Archivable=false else model:ClearAllChildren() end for r=1,blocks do bl=Instance.new("Part",model) bl.FormFactor="Custom" bl.Anchored=true bl.Size=Vector3.new(1,1,1) plc=(plz.Character.Torso.CFrame*CFrame.Angles(0,math.rad(90),0)):toWorldSpace(CFrame.new() + (CFrame.new() * CFrame.Angles(math.rad(r*(360/blocks)),0,0)).lookVector * (.5*diam)) bl.CFrame=plc end wait() end)
Optimization 101: don't do what you don't have to. If you can do a calculation or operation beforehand without sacrificing accuracy, do so.
If you can simplify an expression, do so.
A lot of your code doesn't actually produce any noticeable effect and can be done simpler.
Also, while working with CFrames, please never use math.deg
. Angles are always measured in radians, both on ROBLOX and in real life. Degrees are just mythical creatures that should be killed and forever forgotten.
Below, I have reduced the amount of calculations and operations down to what I believe to be an acceptable level without reducing clarity.
-- Settings local diameter = 34 local numberOfBlocks = 36 -- End Settings local player = game.Players.LocalPlayer local blocks = { } local model -- Preliminary math local delta = 2*math.pi/numberOfBlocks local radius = 0.5*diameter function createParts() model = Instance.new("Model", workspace) model.Archivable = false for index = 1, numberOfBlocks do local block = Instance.new("Part", model) block.FormFactor = Enum.FormFactor.Custom block.Anchored = true block.Size = Vector3.new(1, 1, 1) blocks[#blocks + 1] = block end end function update() local root = player.Character.Torso.CFrame*CFrame.Angles(0, 0.5*math.pi, 0) for index = 1, numberOfBlocks do local block = blocks[index] -- Set a pivot, then offset by a certain amount to produce a circle is what you're trying. -- No need to make your math any more complicated than that. block.CFrame = root*CFrame.Angles(index*delta, 0, 0)*CFrame.new(0, 0, radius) end end createParts() game:GetService("RunService").RenderStepped:connect(update)
Instead of constantly creating and removing the parts, just create the parts once and then update the positions only. That way you have less code that is looping.
First, you have to move the static code to the top of the loop, like so:
--I added a local in front of the variables because it uses less memory and the script can access them faster local diam=34 local blocks=36 local plz=game.Players.LocalPlayer local model=Instance.new("Model", workspace) model.Archivable=false
The model is only going to be made once, so that's why we don't need to have it in a loop.
Now, we have a loop that is creating blocks constantly, but we only want it to create the blocks once so that the loop can just access the blocks and change their positions without having to create more blocks. To do this, we'll need to know how to use Tables
Tables are basically arrays that can be used to hold items. So in our case, that table will hold all the bricks that will be in the circle, like so:
--I'm following your syntax formatting. This isn't the way that I normally write syntax (e.g. BlockTable = {} or for i = 1, blocks do) local blockTable={} for r=1,blocks do local bl=Instance.new("Part",model) bl.FormFactor="Custom" bl.Anchored=true bl.Size=Vector3.new(1,1,1) table.insert(blockTable,bl) end
The above code will create all the blocks and insert them into a table called "blockTable"
This allows us to access the table from the loop and change their positions, like so:
--I removed the wait() at the end of the loop because that's a redundant wait(). It won't do anything game:GetService("RunService").RenderStepped:connect(function() for r, bl in pairs(blockTable) do --This is a special for loop that is used to iterate through tables. "r" is the index, which is the position of the element in the table, and "bl" is the element itself local plc=(plz.Character.Torso.CFrame*CFrame.Angles(0,math.rad(90),0)):toWorldSpace(CFrame.new() + (CFrame.new() * CFrame.Angles(math.rad(r*(360/blocks)),0,0)).lookVector * (.5*diam)) bl.CFrame=plc end end)
Final code:
local diam=34 local blocks=36 local plz=game.Players.LocalPlayer local model=Instance.new("Model", workspace) model.Archivable=false local blockTable={} for r=1,blocks do local bl=Instance.new("Part",model) bl.FormFactor="Custom" bl.Anchored=true bl.Size=Vector3.new(1,1,1) table.insert(blockTable,bl) end game:GetService("RunService").RenderStepped:connect(function() for r, bl in pairs(blockTable) do local plc=(plz.Character.Torso.CFrame*CFrame.Angles(0,math.rad(90),0)):toWorldSpace(CFrame.new() + (CFrame.new() * CFrame.Angles(math.rad(r*(360/blocks)),0,0)).lookVector * (.5*diam)) bl.CFrame=plc end end)
Hope this helped!
Removing and creating that many instances every render frame could be very hard on weaker processors. I recommend just updating the CFrame of all these blocks every render frame to help increase performance.
I also believe that making functions for reused code makes it more efficient, but even if it doesn't It still makes the script cleaner and easier to read.
local blocks= {} local diam = 34 local blocks = 36 local model = Instance.new("Model", workspace) local plz = game.Players.LocalPlayer model.Archivable=false local function CalculateCFrame(r) return (plz.Character.Torso.CFrame*CFrame.Angles(0,math.rad(90),0)):toWorldSpace(CFrame.new() + (CFrame.new()*CFrame.Angles(math.rad(r*(360/blocks)),0,0)).lookVector*(.5*diam)) end local function CreatePart(r) bl=Instance.new("Part",model) bl.FormFactor="Custom" bl.Anchored=true bl.Size=Vector3.new(1,1,1) bl.CFrame=CalculateCFrame(r) table.insert(parts, bl) end for r=1,blocks do CreatePart(r) end game["Run Service"]:RenderStepped:connect(function() for r, block in ipairs (blocks) do block.CFrame = CalculateCFrame(r) end end)