Any efficient way to prevent while true loops from causing lag?

Recently I have been working on an obby type game that contains a lot of moving models. And in order to move these models I have been using tweens and while true do loops so that these models will move forever. At first it was working well, but now I am experiencing a bit of lag when I play test the game and think that it has something to do with these loops running. So I was wondering if there is a more efficient way to make these models move instead of using while true do loops.

Here is the type of script that I have which is parented to most of these models:

local TweenService = game:GetService("TweenService")

local Model = script.Parent.PrimaryPart
local Start = game.Workspace.TimeRunLevel.StartParts.Start2
local End = game.Workspace.TimeRunLevel.EndParts.End2

local debounce = false
local cooldown = 0.5

Model.Touched:Connect(function(hit)
	local humanoid = hit.Parent:FindFirstChildWhichIsA("Humanoid")
	if debounce == false then
		if humanoid then
			if debounce == false then
				debounce = true
				humanoid.Health -= 50
				task.wait(cooldown)
				debounce = false
			end
		end
	end
end)

local tweenInfo = TweenInfo.new(
	2,
	Enum.EasingStyle.Sine,
	Enum.EasingDirection.InOut,
	0,
	false
)

while true do
	local tween = TweenService:Create(Model, tweenInfo, {CFrame = CFrame.new(End.Position)})

	tween:Play()

	tween.Completed:Wait()
	
	local tween = TweenService:Create(Model, tweenInfo, {CFrame = CFrame.new(Start.Position)})

	tween:Play()

	tween.Completed:Wait()
end

A model will move back and forth forever as long as the server is running using a tween.

Other games unload moving parts that aren’t in the player’s proximity. You can try something similar.

Try running the script as a local script on the client, tweens are often smoother there. Also as @sharker12312 mentioned you should only tween/animate what the player can see(which is much easier to do from the client).

How would I go about doing that?

(This is just an example)

--Server Sided Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenRemote = Instance.new("RemoteEvent")
TweenRemote.Name = "TweenRemote"
TweenRemote.Parent = ReplicatedStorage

-- Function to handle the client request to start the tween
TweenRemote.OnServerEvent:Connect(function()
    -- Broadcast the request to all clients
    TweenRemote:FireAllClients()
end)
--Client Sided-Script (such as in starterplayerscripts)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenRemote = ReplicatedStorage:WaitForChild("TweenRemote")

-- Function to start the tween
local function startTween()
    local targetObject = workspace.PartToTween -- Replace with the object you want to tween

    -- Create a TweenInfo object to define the tween properties
    local tweenInfo = TweenInfo.new(
        2,                   -- Duration (in seconds)
        Enum.EasingStyle.QuadOut, -- Easing style
        Enum.EasingDirection.Out,  -- Easing direction
        0,                   -- Repeat count (0 for no repeat)
        false,               -- Reverses after each repeat
        0                    -- Delay between repeats (in seconds)
    )

    -- Create a new Tween
    local tween = game:GetService("TweenService"):Create(targetObject, tweenInfo, {Size = Vector3.new(2, 2, 2)})

    -- Start the Tween
    tween:Play()
end

-- Function to receive the request from the server and start the tween
TweenRemote.OnClientEvent:Connect(startTween)