I've been working on this damage script thing for a game and basically whenever a part named "Destroyable" is within the range of the destroy part (where this script is located,) it gets unanchored and its velocity is changed, now I know doing this will cause lag too but I'm not concerned about that. Whenever I test ingame there are small lag spikes that are incredibly annoying, I'm pretty it's because of GetDescendants() and GetChildren(), though if I am correct does anyone know how I can prevent it? Thanks for reading! :)
while true do
wait(0.3)
local DISVALUE = script.Parent.Distance.Value
local DESVALUE = script.Parent.DE.Value
local partsW = game.Workspace:GetChildren()
if DESVALUE == 1 then
for i = 1,#partsW do
if partsW[i]:IsA("Model") and partsW ~= script.Parent.Parent then
local partsGet = partsW[i]:GetDescendants()
for i = 1,#partsGet do
if partsGet[i]:IsA("Part") or partsGet[i]:IsA("WedgePart") or partsGet[i]:IsA("UnionOperation") then
local dis = (partsGet[i].Position-script.Parent.Position).Magnitude
if partsGet[i].Name == "Destroyable" then
if dis< 500 then
local thisisaPart = partsGet[i]
thisisaPart.Anchored = false
thisisaPart.Velocity = Vector3.new(math.random(-100,100),math.random(20,40),math.random(-100,100))
end
end
end
end
end
end
wait(1)
end
end

3 comments
Adding a longer wait time, at the start/end of the script might help your problem, or maybe adding more waits throughout it.
Not sure if you're going to see this reply but I want the script to register parts once they're within range.
A good way is to parent all parts with the Destroyable name into a Folder into Workspace, this will both save resources and time while checking. Indead of using GetDescendants() on a GetChildren() you would just do GetChildren() on the folder and turning it into a single loop instead of 2. Depending on the size of the game, GetDescendants() can be a very intensive function.