Optimize Pet Follow?

I have this pet follow script that runs on the client. And it’s script activity is going above 50%.
image

Here’s the script:

local runService = game:GetService("RunService")
local ts = game:GetService("RunService")

local playerPets = workspace:WaitForChild("Workers")

local updateOnRender = true
local circularPositioning = false
local circle = math.pi * 2

local function getPosition(angle, radius) -- this is for circular positioning
	local x = math.cos(angle) * radius
	local z = math.sin(angle) * radius
	return x, z
end

local function positionWorkers(character, plrWorkFocus, folder, dt)

	local charRP = character.PrimaryPart

	for i, worker in pairs(folder:GetChildren()) do
		
		-- values
		local valuesFolder = worker.values
		local workerRP = worker.PrimaryPart
		
		if not workerRP then continue end
		
		local _, characterSize = character:GetBoundingBox()
		local _, workerSize = worker:GetBoundingBox()
		
		local radius, angle, x, z, y
		local workerAttach = charRP:FindFirstChild("workerAttach" .. i)
		
		-- positioning type
		if not circularPositioning and plrWorkFocus.Value == nil and workerAttach then
			x, z, y = workerAttach.Position.X, workerAttach.Position.Z, workerAttach.Position.Y
		else
			if plrWorkFocus.Value ~= nil then
				radius = 4
			else
				radius = 3 + #folder:GetChildren()
			end
			
			angle = i * (circle / #folder:GetChildren())
			x, z = getPosition(angle, radius)
			
			y = - characterSize.Y/2 + workerSize.Y/2.1
		end

		local sin = (math.sin(15 * time() + 1.6)/.5)+1
		local cos = math.cos(7 * time() + 1)/4

		local lerpSpeed = 0.1
		local endCF
		
		-- on ore?
		if plrWorkFocus.Value ~= nil and plrWorkFocus.Value:GetAttribute("Health") > 0 then
			
			local _, oreSize = plrWorkFocus.Value:GetBoundingBox()
			y = - oreSize.Y/2 + workerSize.Y/1.55
			
			local position = (plrWorkFocus.Value.PrimaryPart.CFrame * CFrame.new(x, 0, z)).p
			local lookAt = plrWorkFocus.Value.PrimaryPart.Position
			endCF = CFrame.new(position, lookAt) * CFrame.new(0, y, 0)
			lerpSpeed *= 2
		else
			endCF = character.PrimaryPart.CFrame * CFrame.new(x, y, z)
		end
		
		-- distance for lerp so if too far is fast
		local distanceFromPlr = (workerRP.Position - endCF.Position).Magnitude

		lerpSpeed = if dt then 1 - lerpSpeed ^ dt else lerpSpeed
		if distanceFromPlr >= 20 then lerpSpeed = 1 end
		
		-- set the final lerp
		worker:SetPrimaryPartCFrame(workerRP.CFrame:Lerp(endCF, lerpSpeed))
		
	end
end


local function onRender(dt)
	for _, PlrFolder in pairs(playerPets:GetChildren()) do
		if #PlrFolder:GetChildren() == 0 then continue end
		
		local Player = game.Players:GetPlayerByUserId(PlrFolder.Name)
		if Player == nil then continue end
		
		local character = Player.Character or nil
		local scriptableValues = Player:FindFirstChild("scriptableValues")
		if character == nil or not scriptableValues or not scriptableValues:FindFirstChild("minerFocus") then continue end
		
		task.spawn(positionWorkers, character, scriptableValues.minerFocus, PlrFolder, dt)
	end
end

-- loops
if updateOnRender then
	runService.PreRender:Connect(function(dt)
		task.spawn(onRender, dt)
	end)
else
	while task.wait() do
		task.spawn(onRender)
	end
end

The script avtivity shown is when I’m using PreRender, but it’s basically the same with task.wait()

3 Likes

A different way you could create the pet system is run a function once that calculates the positions. With these positions weld parts that are connected the humanoid root and then use align position and orientation to position the pets.
This way there is no need for any loops at all.

I tried that, but the pets never moved, they just stayed in the same spot they were cloned. Is it because they are humanoids?

How are you using the align position?
You should have it aligning a part from the pet that has all the other parts welded to it. Having a humanoid shouldn’t affect this as I’ve used align position on players in my past projects.

When I tried it I used attachments connected to the hrp of the player and set the align position to go to it. You said i need parts, does it make a difference?

Attachments are fine. Is the pet welded correctly?

oh wqait its wokring, but the pet is like laggin behind really badly why is that?

wait now its like glued to the attachemtn i want it to slowly get there

i thgink i need to change this settings, what is best?
image

just play around with it and find whats best, just make sure rigidity enabled isnt on

ive been trying to figure it out for a while, do you mind tell me how you made yours in the past if you even have?

I haven’t made a pet follow system but just opened up studio and used these settings and it worked pretty smooth:
image

i have the same settings, but my pet is acting likes its welded to the attachment instead of smoothly going to it. can i not do that with align position?

that’s strange, is yours set up similarly to this:
image

yes its exactly like that, but the pet isnt inside the player its in a folder in workerspace

could you show me the code? There might be something affecting it

	local attach = plr.Character.PrimaryPart["workerAttach" .. workerNum]
	worker.PrimaryPart.AlignPosition.Attachment1 = attach
	worker.PrimaryPart.AlignOrientation.Attachment1 = attach
	
	delay(1, function()
		worker.PrimaryPart:SetNetworkOwner(plr)
	end)

it just sets the attachments and then sets the network ownership to the player, if i dont set it to the player the pet lags behind a lot

Ye, I don’t know what’s wrong, I suggest playing around with different stuff to see if it fixes it or just try a new method

its because of the repeated math calculations, try to find a way to lower the math calculations done every frame, or delete the script and redo it. I would make one while loop with an interval of .1 seconds using task.wait() and it assigns a local variable pos thats equal to the players humanoid root part, then it checks if the Players humanoidrootpart position is the same as pos and if its not make a tween to go to the position next to the player. do the tweening in a server script if your game is multiplayer, else, make it in a local script.

or just use a weldconstraint lol.