My pet script is so laggy and i cant figure out why?

Ok so i got a pet script from someone helping me with bugs earlier and it works great, its exactly what i wanted, But, it lags SO MUCH!

ive tried everything i know about optimizing code (Not that much lol) but cant seem to fix it.

so only one solution! back to the dev forum !!

heres my code

-- module
local Pets = {}
Pets.__index = Pets

-- variables

-- players and their owned pets with a type so we understand the structure.
-- This type definition helps with understanding the structure of serverPets.
type PlayerPetArray = { [Player]: {typeof(setmetatable({}, Pets))} }
-- serverPets stores a table of pets for each player.  The keys are Player objects, and the values are arrays of pet objects.
local serverPets: PlayerPetArray = {}

-- This function creates a new entry in serverPets for a player if one doesn't exist.
local function createEntry(player: Player)
	serverPets[player] = {} -- Initialize an empty table for the player's pets.
	return {} -- Return an empty table.  This isn't strictly necessary, but it mirrors how Pets.new works.
end

local methods = {} -- This table will hold the methods for the Pet objects.
function Pets.new(player: Player,pet)
	-- get the player's owned pets or create a new empty table of pets
	-- If the player already has pets, retrieve them; otherwise, create a new entry for the player.
	local theirPets = serverPets[player] or createEntry(player)

	-- Create a new part to represent the pet.
	local newPet = pet:Clone()
	newPet.Name = `{player.Name}'s Pet ({#theirPets})` -- Give the pet a name based on the player and pet count.
	newPet.Parent = workspace -- Parent the pet to the workspace.

	table.insert(serverPets[player], newPet) -- Add the new pet's part to the player's pet array.

	-- pet properties (example)
	-- Create a new pet object using a metatable to give it methods.
	local self = setmetatable({}, Pets)
	self.petName = "john" -- Example pet name.
	self.petRarity = "ultra rare glowy" -- Example pet rarity.
	self.instance = newPet -- Store the pet's part instance.

	return self -- Return the new pet object.
end

-- Method to move the pet.
function Pets:Move(newCFrame: CFrame)
	local instance: Part = self.instance -- Get the pet's part instance.
	instance.CFrame = newCFrame -- Set the pet's CFrame.
end

local RunService = game:GetService("RunService")

-- This function is called every heartbeat to update the pet positions.
local function onHeartbeat(deltaTime: number)
	for player, petArray in pairs(serverPets) do -- Iterate through each player and their pets.
		local character = player.Character -- Get the player's character.
		if character then
			local hrp = character:FindFirstChild("HumanoidRootPart") -- Get the HumanoidRootPart.
			if hrp then
				local baseCFrame : CFrame = hrp.CFrame -- Get the HRP's CFrame.
				local position : Vector3 = baseCFrame.Position -- Get the HRP's position.
				local rightVec : Vector3 = baseCFrame.RightVector -- Get the HRP's right vector.
				local petCount : number = #petArray -- Get the number of pets the player has.
				
				for i, pet in ipairs(petArray) do -- Iterate through each of the player's pets.
					local targetPos: Vector3 -- Declare the target position.
					local offsetDistance : number = 5 -- Distance between the player and the pets.
					if petCount == 2 then -- Special case for two pets: one on each side.
						if i == 1 then
							targetPos = position + rightVec * offsetDistance
						else -- i == 2
							targetPos = position - rightVec * offsetDistance
						end
					else -- For more than two pets, arrange them in a circle.
						local angle : number = (2 * math.pi / petCount) * (i - 1) -- Calculate the angle for each pet.
						local offset : Vector3 = Vector3.new(math.cos(angle) * offsetDistance, 0, math.sin(angle) * offsetDistance) -- Calculate the offset.
						targetPos = position + baseCFrame:VectorToWorldSpace(offset) -- Apply the offset relative to the player's CFrame.
					end
					local targetCFrame = CFrame.new(targetPos) -- Create the target CFrame.
					local lerpAlpha = math.clamp(10 * deltaTime, 0, 1) -- Calculate the interpolation alpha.
					pet:SetPrimaryPartCFrame(pet.PrimaryPart.CFrame:Lerp(targetCFrame, lerpAlpha))  -- Smoothly move the pet to the target position.
				end
			end
		end
	
	end

end

RunService.Heartbeat:Connect(onHeartbeat)

return Pets -- Return the Pets module.

Thanks for any help!

edit: before anyone says “Look up how to optimize code” i did and it did not help.

2 Likes

The pet visuals could be done on each player’s client instead of the server; this also gives you a way for a player to hide others’ (or their own) pets.

You can use RenderStepped in a LocalScript to move the pets on each player’s client.

4 Likes

Your script lags because it updates pet positions every frame, which is too demanding. reduce the update frequency and offload heavy tasks to separate threads.

2 Likes

But how would i reduce the update frequency and also have the pets follow the player without falling behind? would a while loop be better ?

1 Like

My guess would be that moving the pets is what is laggy, but I don’t mean your code, I mean the roblox engine

However, there are tricks to speed that up by a lot
First of all SetPrimaryPartCFrame is deprecated, and PivotTo() should be used instead, but even PivotTo() is laggy

The most efficient way to move models around is by moving the rootpart of the model. The rootpart needs to be the only anchored part, and should be welded directly or indirectly to every other part

By doing so, you can update the CFrame property of the rootpart, rather than moving the model. workspace:BulkMoveTo() can also be used, but the performance increase isn’t as drastic

2 Likes

I dont even know how i would really do this.

im pretty new to using stuff like this :confused:

1 Like

I will try this, thank you

MoreCharrsss

2 Likes

You shouldn’t, unless maybe you make a throttling system for far away pets, but imo not that worth doing

Simulating the pets on the client however will help as you’d reduce network usage, and the client wont have to simulate every pet (you can make a system to only simulate pets close by)

But ultimately, if it lags on the server, it is likely to still lag the client, so moving the pets using the rootpart is kind of required

3 Likes

Use a time-based system that updates pet positions at fixed intervals (eg. every 0.1 secs) and smooths movement with Lerp . Avoid while loops, as they block the main thread and can cause performance issues.

2 Likes

Use RemoteEvents to tell each client which pets are currently active. Then, simply locally move the pets.

Remember that the player would only be able to see their pets this way. If you wanted every player’s pet to be displayed for all players, you’d have to keep track of every single pet currently active.

3 Likes

I dont think this would really work for my game, because i do want all pets to be visible to others.

1 Like

From experience, the lag doesn’t come from calculating the position. While CFrame math is on the expensive side, moving objects around, especially models using PivotTo() is way more significant performance wise

To find these kinds of optimizations, the micro profiler is extremely useful, as it tells precisely what takes a long time

If I remember correctly, tweens aren’t more performant than changing the CFrame, or at least not by a lot. However, tweenServices activity is not shown in the script activity tab, because it runs in another thread I believe

3 Likes

How do i use the Micro profiler? ive never even heard of it

2 Likes

It would work just fine - you’d just have to locally render every player’s pets on every player’s client. A bit more logic involved but nothing too difficult

3 Likes

Sorry for not providing the link earlier, I’m on my phone so it’s not very easy to do

The micro profiler is complicated to understand, but very powerful. I’m not sure I should recommend you learn to use it as a beginner, but nothing is better to optimize a game

1 Like

Now something strange is happening…
whenever i have

debug.profilebegin

and

debug.profileend

inside the function, the lag basically stops?

but its giving a warning every second

ive been scripting on roblox for 2 years but its only just recently that ive begun to understand what im doing :sob:

for the majority of the 2 years i would just get free models and make bad scripts then try to publish a game tho :confused:

1 Like

like i said though, someone helped me do this on the dev forum, so most of this code i barely even understand.

it would be very difficult for me to move over code that i dont understand to every players client.

(i have been working towards being able to read and write advanced code like this though)

O MY GOSHH BEFORE ANYONE ELSE REPLIES I GOT IT!!!

idk why i didint do this sooner but deleting all my plugins fixed it.

i decided to do this after the studio viewport was lagging too, and that was the whole issue i guess.

(Also obviously i took some of the suggestions from here to make the code less laggy)

Thanks so much for the help!!

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.