Need help with roblox physics

Hello developers, I need your assistance today on a VFX module for a custom pet system. I ran into a strange issue which appears to be faulty replication from client to server.

From the other client’s point of view, the VFX appears to be working fine but the part eventually somehow reaches the maximum negative Y limit and gets destroyed, when I set FallenPartsDestroyedHeight to a larger negative value, the VFX parts remain for a noticeably prolonged amount of time.

I’m pretty certain that the VFX part’s network ownership are given to the player. And in the meantime, here’s a part of the VFX code.

function PurpleSpirit:Start()
	local absoluteAngle1 = CFrame.Angles(0, 0, 0)
	local absoluteAngle2 = CFrame.Angles(0, 0, 0)
	local presentColorType = 1
	local lastColorTick = tick()
	self._maid.Thread = RunService.Heartbeat:Connect(function(delta)
		local success = xpcall(function()
			local rCF = self._rootPart.CFrame
			absoluteAngle1 *= CFrame.Angles(0, (self._alpha-2) * delta, 0)
			absoluteAngle2 *= CFrame.Angles(0, -(self._alpha * delta), 0)
			--print(absoluteAngle, o)
			self._auraFolder.Object1.CFrame = absoluteAngle1 + self._rootPart.Position + self._objectOffset[self._auraFolder.Object1]
			self._auraFolder.Object2.CFrame = absoluteAngle2 + self._rootPart.Position + self._objectOffset[self._auraFolder.Object2]
			if tick() - lastColorTick > self._colorInterval * 2 then
				TweenObject(self._auraFolder.Object1, self._maid, self._colorInterval, {
					Color = presentColorType == 1 and self._colorValue2 or self._colorValue1
				}, Enum.EasingStyle.Sine)
				presentColorType = presentColorType == 1 and 2 or 1
				lastColorTick = tick()
			end
		end, function(...)
			-- handle error
			if not self._debugMode then return; end
			warn(..., debug.traceback("\n", 2))
		end)
		if not success then
			self:Stop() -- disconnect thread
		end
	end)
end

function PurpleSpirit:CalculateOffset() -- calculate the offset of all objects from the centre
	local centre = GetBoundingBox(self._auraFolder).Position -- .p is deprecated
	for _, object in pairs(self._auraFolder:GetChildren()) do
		self._objectOffset[object] = Vector3.new(object.Position - centre)	
	end
end

PurpleSpirit.new = function(root, object, configuration, callbackMaid)
	local self = setmetatable({
		_rootPart = root.RootPart,
		_auraFolder = object,
		_config = configuration,
		_debugMode = true,
		_maid = callbackMaid,
		_objectOffset = {},
		-- VFX Settings and Default configurations
		_alpha = configuration.Alpha and configuration.Alpha or 2,
		_colorValue1 = Color3.fromRGB(98, 37, 209),
		_colorValue2 = Color3.fromRGB(0, 255, 255),
		_colorInterval = 2
	}, PurpleSpirit)
	
	self._maid:GiveTask(self)
	self:CalculateOffset()
	
	return self;
end

It would be lovely if anyone can help.

I already found the reason why the glitch on the second video is happening, I believe it’s the result of the client not running (or at a lower rate) whilst I switched to server’s view but that still doesn’t explain why the vfx parts are destroyed subsequently, after they apparently reach the maximum fallen height. I say apparently because in my tests, the CFrame and Position doesn’t seem abnormal (when i print the values out and checked on studio’s properties tab), the values in which are position and CFrame are completely normal in this case.

Side Info that may be helpful to solve this: the module is ran locally and the part network ownerships are given to the client (there’s a possibility the part network ownership isn’t give to the client so I can’t rub that off)

I don’t have a great understanding on how Roblox’s physics works, so anyone who has an idea can correct my mistakes.

Edits: Grammar Mistakes

Hello, for anyone that is wondering or having a similar issue it turns out the problem was caused by Velocity. All you have to do it set velocity to 0

function PurpleSpirit:Start()
	local absoluteAngle1 = CFrame.Angles(0, 0, 0)
	local absoluteAngle2 = CFrame.Angles(0, 0, 0)
	local presentColorType = 1
	local lastColorTick = tick()
	self._maid.Thread = RunService.Heartbeat:Connect(function(delta)
		local success = xpcall(function()
			local rCF = self._rootPart.CFrame
			absoluteAngle1 *= CFrame.Angles(0, (self._alpha-2) * delta, 0)
			absoluteAngle2 *= CFrame.Angles(0, -(self._alpha * delta), 0)
			--print(absoluteAngle, o)
+			self._auraFolder.Object1.Velocity = Vector3.new(0, 0, 0)
+			self._auraFolder.Object2.Velocity = Vector3.new(0, 0, 0)
			self._auraFolder.Object1.CFrame = absoluteAngle1 + self._rootPart.Position + self._objectOffset[self._auraFolder.Object1]
			self._auraFolder.Object2.CFrame = absoluteAngle2 + self._rootPart.Position + self._objectOffset[self._auraFolder.Object2]
			if tick() - lastColorTick > self._colorInterval * 2 then
				TweenObject(self._auraFolder.Object1, self._maid, self._colorInterval, {
					Color = presentColorType == 1 and self._colorValue2 or self._colorValue1
				}, Enum.EasingStyle.Sine)
				presentColorType = presentColorType == 1 and 2 or 1
				lastColorTick = tick()
			end
		end, function(...)
			-- handle error
			if not self._debugMode then return; end
			warn(..., debug.traceback("\n", 2))
		end)
		if not success then
			self:Stop() -- disconnect thread
		end
	end)
end