Pet Script Causing Huge Lag

Hey developers,
I’ve been working on a pet following system for the past few days, but I noticed it caused very noticeable lag when the player equips pets.

local function getPosition(angle, radius)
	local x = math.cos(angle) * radius
	local z = math.sin(angle) * radius
	return x, z

local function positionPets(character, folder, dt)
	for i, pet in pairs(folder:GetChildren()) do
		local radius = 4+#folder:GetChildren()
		local angle = i * (circle / #folder:GetChildren())
		local x, z = getPosition(angle, radius)
		local _, characterSize = character:GetBoundingBox()
		local _, petSize = pet:GetBoundingBox()

		local offsetY = - characterSize.Y/2 + petSize.Y/2
		local sin = (math.sin(15 * time() + 1.6)/.5)+1
		local cos = math.cos(7 * time() + 1)/4
		if character.Humanoid.MoveDirection.Magnitude > 0 then
			if pet:FindFirstChild("Walks") then
				pet:SetPrimaryPartCFrame(pet.PrimaryPart.CFrame:Lerp(character.PrimaryPart.CFrame *, offsetY+sin, z) * CFrame.fromEulerAnglesXYZ(0,0,cos),0.1))
				pet:SetPrimaryPartCFrame(pet.PrimaryPart.CFrame:Lerp(character.PrimaryPart.CFrame *, offsetY/2+math.sin(time()*3)+1, z),0.1))
			if pet:FindFirstChild("Walks") then 
				pet:SetPrimaryPartCFrame(pet.PrimaryPart.CFrame:Lerp(character.PrimaryPart.CFrame *, offsetY, z) ,0.1))
				pet:SetPrimaryPartCFrame(pet.PrimaryPart.CFrame:Lerp(character.PrimaryPart.CFrame *, offsetY/2+math.sin(time()*3)+1, z) ,0.1))


game["Run Service"].RenderStepped:Connect(function(deltaTime)
	for _, Player in pairs(game.Players:GetChildren()) do
		if workspace.EquippedPets:FindFirstChild(Player.Name) and Player.Character then
			local character = Player.Character
			positionPets(character, workspace.EquippedPets:FindFirstChild(Player.Name), deltaTime)

The pet follow script is a localscript in StarterPlayerScripts, and the purpose of it is to display every players’ pets on the client so that the server doesn’t lag. However, I still notice a lot of lag whenever I equip pets, and it would probably only get worse as more players join the game.

Any help or suggestions would be much appreciated :slight_smile:

Sounds like you are asking a lot each RenderStepped frame.

You check through every player’s children.
You then go through every pet and set each pet’s Position in the radius according to the calculations.
Is the createPetTag function possibly causing lag? You didn’t include that section of code.
Then it looks like you Lerp the pet Position.

Why not check every .1 second instead of RenderStepped (which afaik are about 1/60 of a second) then Lerp your pets. Lerping allows them to move smoothly so updating each RenderStepped seems to be overkill.
Also instead of calculating the radius each time couldn’t you just check to see if the number of pets has changed. If it hasn’t you don’t need to recalculate their offset each time.

1 Like

A lower update time together with bodyforces would help.
The bodyforces can smooth out the choppy movement a low tick causes.

As @Scottifly suggested, may we see the createPetTag function?

Additionally depending on how high poly your pet models are, it might be helpful to try if lag is reduced if you use temporary parts as your pets. So you can isolate wether the issue is truly in code or not.

When I change the RenderStepped to while task.wait(.1) do, the pets look like they’re lagging behind the player.

Use tweenservice and tween to the new position in .1 seconds so that it isn’t lagging behind.

1 Like

Here is the function

local function createPetTag(pet)
	local cframe, size = pet:GetBoundingBox()
	local tag = pet.PrimaryPart:FindFirstChild("PetTag") or game.ReplicatedStorage.PetTag:Clone()
	local yValue = size.Y/2
	tag.StudsOffset =, yValue, 0)
	local rarity = "Epic"
	for moduleEgg, petNumber in pairs(chancesModule.PetChances) do
		for _, petInfo in pairs(petNumber) do
			if petInfo.Name == pet.Name then
				rarity = petInfo.Rarity
	for petName, petNumber in pairs(chancesModule.RobuxPets) do
		if petName == pet.Name then
			rarity = petNumber.Rarity
	local textGradientColor = tag.Rarity:FindFirstChildOfClass("UIGradient") or game.ReplicatedStorage.PetRarityColors:FindFirstChild(rarity):Clone()
	textGradientColor.Parent = tag.Rarity
	tag.Rarity.Text = rarity
	tag.Parent = pet.PrimaryPart
1 Like

Is it really necessary to update the tag 60 times a second?

I believe a tag should only be set once for a pet, and left at that.


So in your positionPets function you’re waiting .1 seconds for your Lerp.
If you decrease that number then it’ll probably help out since my recommendation was to only fire the entire script every .1 second.
Doing it twice will of course slow it down.

Actually I’ve seen other players actually request help with ways to have their pets slightly lag behind so they aren’t always static to the player and give a more ‘realistic’ movement.

1 Like