Client-Sided Moving Platforms randomly breaking

Hello,
I’m working on a Tower of Hell-style game and I’m trying to add client-sided moving platforms to it which use PrismaticConstraints. However, there are several issues with them. Sometimes the platform will fly out of the map, which is already bad in itself. But the main issue is that they randomly break sometimes - they just stand in place and not move. This is kinda rare though, so I haven’t really been able to properly debug this. But when I did see it happen, ALL moving platforms were broken for several people in the server while still working fine for some. I have no idea what is causing this issue and have been trying to fix it for days.

Here is the full file with the moving platforms:
MovingPlatforms.rbxl (60.2 KB)

And here is my LocalScript alone:

local function setupMovingPlatform(model)

	if model:GetAttribute('Setup') then return end
	model:WaitForChild("part1")
	model:WaitForChild("platform")
	model:WaitForChild("part2")
	model.platform:WaitForChild("antigrav")
	local m = model
	model = m:Clone()
	model:WaitForChild("part1")
	model:WaitForChild("platform")
	model:WaitForChild("part2")
	model.platform:WaitForChild("antigrav")
	model.Parent = m.Parent
	m:Destroy()
	model:SetAttribute('Setup', true)
	model.platform.Anchored = false

	local TweenService = game:GetService('TweenService')
	local SPEED = model:GetAttribute('Speed')
	local start = model.part1
	local finish = model.part2

	local attach0 = Instance.new('Attachment')
	attach0.CFrame = CFrame.new()
	attach0.Parent = model.platform

	local attach1 = Instance.new('Attachment')
	attach1.CFrame = finish.CFrame
	attach1.Parent = game.Workspace.Terrain

	local pris = Instance.new('PrismaticConstraint')
	pris.ActuatorType = Enum.ActuatorType.Motor
	pris.MotorMaxForce = math.huge
	pris.Attachment0 = attach1
	pris.Attachment1 = attach0
	pris.Parent = model.platform

	local forward = true

	local function smoothVelocity(targetVelocity, duration)
		local info = TweenInfo.new(duration, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut)
		local velocityGoal = { Velocity = targetVelocity }
		local tween = TweenService:Create(pris, info, velocityGoal)
		tween:Play()
	end

	smoothVelocity(SPEED, 2)

	start.Touched:Connect(function(hit)
		if hit == model.platform and not forward then
			forward = true
			smoothVelocity(0, 1)
			wait(1)
			attach1.CFrame = finish.CFrame
			smoothVelocity(SPEED, 2)
		end
	end)

	finish.Touched:Connect(function(hit)
		if hit == model.platform and forward then
			forward = false
			smoothVelocity(0, 1)
			wait(1)
			attach1.CFrame = start.CFrame
			smoothVelocity(-SPEED, 2)
		end
	end)

	local function updateGravity()
		model.platform.antigrav.Force = Vector3.new(0, model.platform:GetMass() * workspace.Gravity, 0)
	end
	updateGravity()
	workspace.Changed:Connect(updateGravity)
end

workspace.DescendantAdded:Connect(function(v)
	if v:IsA('Model') and v:HasTag('MovingPlatform') and v:GetAttribute('Speed') then
		task.spawn(function()
			setupMovingPlatform(v)
		end)
	end
end)

for _, v in pairs(workspace:GetDescendants()) do
	if v:IsA('Model') and v:HasTag('MovingPlatform') and v:GetAttribute('Speed') then
		task.spawn(function()
			setupMovingPlatform(v)
		end)
	end
end

Can somebody help me out? Thanks!

3 Likes

MovingPlatforms.rbxl (60.3 KB)

Just ran down the script replacing what looked off (wasn’t much).
Seems to run fine, you’ll have to test it for yourself..

Counting on that passing your inspection.. if so, some more script refinements:

--LocalScript in StarterPlayerScripts
local TweenService = game:GetService("TweenService")

local function setupPlatform(m)
	if m:GetAttribute("Setup") then return end
	m:WaitForChild("part1")
	m:WaitForChild("platform")
	m:WaitForChild("part2")
	m.platform:WaitForChild("antigrav")

	local clone = m:Clone()
	clone.Parent = m.Parent
	task.defer(function() m:Destroy() end)
	clone:SetAttribute("Setup", true)
	clone.platform.Anchored = false

	local a0 = Instance.new("Attachment")
	a0.Parent = clone.platform

	local a1 = Instance.new("Attachment")
	a1.Parent = workspace.Terrain
	a1.CFrame = clone.part2.CFrame

	local pris = Instance.new("PrismaticConstraint")
	pris.ActuatorType = Enum.ActuatorType.Motor
	pris.MotorMaxForce = math.huge
	pris.Attachment0 = a1
	pris.Attachment1 = a0
	pris.Parent = clone.platform

	local speed = clone:GetAttribute("Speed")
	local forward = true

	local function setVel(v,d)
		local t = TweenInfo.new(d, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut)
		TweenService:Create(pris, t, {Velocity = v}):Play()
	end

	setVel(speed, 2)

	clone.part1.Touched:Connect(function(hit)
		if hit == clone.platform and not forward then
			forward = true
			setVel(0,1)
			task.wait(1)
			a1.CFrame = clone.part2.CFrame
			setVel(speed,2)
		end
	end)

	clone.part2.Touched:Connect(function(hit)
		if hit == clone.platform and forward then
			forward = false
			setVel(0,1)
			task.wait(1)
			a1.CFrame = clone.part1.CFrame
			setVel(-speed,2)
		end
	end)

	local function updateGravity()
		clone.platform.antigrav.Force = Vector3.new(0, clone.platform:GetMass() * workspace.Gravity, 0)
	end

	updateGravity()
	workspace.Changed:Connect(updateGravity)
end

workspace.DescendantAdded:Connect(function(v)
	if v:IsA("Model") and v:HasTag("MovingPlatform") and v:GetAttribute("Speed") then
		task.spawn(setupPlatform, v)
	end
end)

for _,v in ipairs(workspace:GetDescendants()) do
	if v:IsA("Model") and v:HasTag("MovingPlatform") and v:GetAttribute("Speed") then
		task.spawn(setupPlatform, v)
	end
end

This is good stuff.. nice work here.