Animated Skin System Causing Extreme Lag

I’ve tried making the script local, serverside, changing how it changes. Nothing changes the insane lag its causing.

The code is below:

local RunService = game:GetService("RunService")

local skinparts = {
	["AR"] = {"SkinPart", "SkinPartIn", "SkinPart3", "SkinPart4"},
	["LMG"] = {"SkinPart", "SkinPartIn", "MeshPart"},
	["ML"] = {"SkinPart"},
	["MLP"] = {"SkinPart"},
	["OPL"] = {"SkinPart", "SkinPartIn"},
	["PL"] = {"SkinPart", "SkinPartIn"},
	["SG"] = {"SkinPart", "SkinPartIn"},
	["SMG"] = {"SkinPart", "SkinPartIn"},
	["SR"] = {"SkinPart", "SkinPartIn"}
}

function skinCycle(part)
	local connection
	local function runse()
		for i, v in ipairs(part:GetDescendants()) do
			if(v:IsA("Texture")) then
				if(v.OffsetStudsU > 2)then
					v.OffsetStudsU = 0
				end
				v.OffsetStudsU = v.OffsetStudsU + 0.005
			end
		end
	end
	local function runchris()
		for i, v in pairs(skinparts[part.Name]) do
			if(part.Build[v].TextureID == "rbxassetid://2332492") then
				part.Build[v].Material = Enum.Material.ForceField
				print(part.Build[v])
				spawn(function()
					repeat
						part.Build[v].Color = Color3.fromRGB(255,0,0)
						wait(2)
						part.Build[v].Color = Color3.fromRGB(0,255,0)
						wait(2)
					until connection == false
				end)
			end
		end
	end
		connection = RunService.RenderStepped:Connect(runse)
		runchris()
	part.AncestryChanged:connect(function()
		if (not part:IsDescendantOf(workspace)) then
			pcall(function()connection:Disconnect()end)
			connection = false
		end
	end)
end

game.ReplicatedStorage.PlayerWeaponAdded.OnClientEvent:Connect(function(itemstoupdate)
	
	for i, v in ipairs(itemstoupdate) do
		skinCycle(v)
	end

end)

I think the problem is the loops. Maybe put a wait() in each big loop to stop the lag.

you don’t need to use RenderStepped for texture updating in order for it to looks seemless, having each part’s descendants update at 60 fps is a textbook definition of unoptimized

you can get away with updating it at around 24 fps (1 / 24 of a second) and still have it looks good. and instead of cycling through each of the part’s descendants, you should just cycle through everything once, add every valid textures into a table, and then cycle through that table to update each textures every loop, this especially matters if your part has a lot of descendants. a minor extra optimization would be to use coroutine instead of spawn, though this hardly matters

1 Like

Updated it to this and still lagging like crazy

--local CollectionService = game:GetService("CollectionService")
local RunService = game:GetService("RunService")

local skinparts = {
	["AR"] = {"SkinPart", "SkinPartIn", "SkinPart3", "SkinPart4"},
	["LMG"] = {"SkinPart", "SkinPartIn", "MeshPart"},
	["ML"] = {"SkinPart"},
	["MLP"] = {"SkinPart"},
	["OPL"] = {"SkinPart", "SkinPartIn"},
	["PL"] = {"SkinPart", "SkinPartIn"},
	["SG"] = {"SkinPart", "SkinPartIn"},
	["SMG"] = {"SkinPart", "SkinPartIn"},
	["SR"] = {"SkinPart", "SkinPartIn"}
}

function skinCycle(part)
	local connection
	local textures = {}
	local newThread1
	local newThread2
	for i, v in ipairs(part:GetDescendants()) do
		if(v:IsA("Texture")) then
			table.insert(textures, v)
		end
	end
	local function runse()
		newThread1 = coroutine.create(function()
			while wait(1/12) do
				for i, v in ipairs(textures) do
					if(v.OffsetStudsU > 2)then
						v.OffsetStudsU = 0
					end
					v.OffsetStudsU = v.OffsetStudsU + 0.025
				end
			end
		end)
		
		coroutine.resume(newThread1)
	end
	local function runchris()
		for i, v in pairs(skinparts[part.Name]) do
			if(part.Build[v].TextureID == "rbxassetid://2332492") then
				part.Build[v].Material = Enum.Material.ForceField
				local newThread2 = coroutine.create(function()
					while true do
						part.Build[v].Color = Color3.fromRGB(255,0,0)
						wait(2)
						part.Build[v].Color = Color3.fromRGB(0,255,0)
						wait(2)
					end
				end)
				coroutine.resume(newThread2)
			end
		end
	end
		runse()
		runchris()
	part.AncestryChanged:connect(function()
		if (not part:IsDescendantOf(workspace)) then
			coroutine.yield(newThread1)
			coroutine.yield(newThread2)
		end
	end)
end

game.ReplicatedStorage.PlayerWeaponAdded.OnClientEvent:Connect(function(itemstoupdate)
	
	for i, v in ipairs(itemstoupdate) do
		skinCycle(v)
	end

end)```

how many items are in the itemstoupdate table and how many textures does the part(s) have? and have you tried testing it with a single texture part?