Pet movement very inconsistent and delayed

Me and my friend created a pet system and it’s very slow and inconsistent. We use tweens to change the pets position and we use a bit of math to make it a circle around the player. Whenever the player moves it feels delayed and when ever you turn the pets forcefully just want to change positions for some reason.

equipCurrentPet.OnServerEvent:Connect(function(plr, petIDCurrent)
	local HRP = plr.Character.HumanoidRootPart
	local humanoid = plr.Character.Humanoid
	for i, v in pairs(plr.inventoryFolder:GetChildren()) do
		if v.petID.Value == petIDCurrent then
			local chosen = v:Clone()
			local newClone = v:Clone()
			newClone.Parent = plr.equipFolder
			chosen.Parent = workspace
			while wait() do
				local index = 0
				for n, k in pairs(plr.equipFolder:GetChildren()) do
					if k.petID.Value == chosen.petID.Value then
						index = n
					end
				end
				local fullCircle = 2 * math.pi
				local radius = 15

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

				local angle = index * (fullCircle / #plr.equipFolder:GetChildren())
				local x, z = getXAndZPositions(angle)

				local position = (HRP.CFrame * CFrame.new(x, 0, z)).p
				local lookAt = HRP.Position

				local goal = {CFrame = CFrame.new(position, lookAt)}
				local petMove = TweenService:Create(chosen, TweenInfo.new(0.1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut), goal)
				petMove:Play()
			end
		end
	end
end)
1 Like

Oh sorry forgot to provide video completely forgot

The biggest problem that you’re probably running into is that your tweens run longer than a traditional wait cycle (which by the way, switch to task library’s wait function moving forward [it works in tandem with the task scheduler and is the modern way to accomplish yielding]).

A global wait cycle that yields its default functionality will yield for roughly .03 seconds. Your tween runs for .1 second (this is the first argument of a TweenInfo object). This means that your code, written as pseudo-code, works like this;

Forever loop{
-> Yield of ~.03 seconds
-> A Tween is created
-> Tween is played (runs for .1 seconds)
}

See the problem?

“Multiple tweens can be played on the same object at the same time, but they must not be animating the same property. If two tweens attempt to modify the same property, the initial tween will be cancelled and overwritten by the most recent tween (see examples).” DevHub source

A majority/all of your tweens do not completely finish which leads to jump cutting when they overwrite their predecessor. Tweens are animations and updates are applied at a faster rate than your global wait, which causes jittering/janky-movement.

Additionally, if it feels too clunky and you want a more traditional pet feel. I would write some math using the magnitude of the distance between the pet and the player to set its pace.

Finally, I would advise you toward writing your pet with movement constraint objects if you struggle to match the pace that a CFrame pet requires/ any other problem. Constraints are your friend, save you a lot of math and memory, and should be used.

Uploading: Desktop 2022.04.03 - 20.35.08.02.DVR.mp4…