Why does this happen and how to fix?

I have an elevator that tweens position back and forth, but when another player views a player in the elevator, their character reacts with the physics properly. But any other players they get whack and start going through the floor. Any ideas how to fix this?

Elevator script I made:

local main = script.Parent
local whichFloor = "lower"
local inRoute = false
local elevatorDingSound = script:WaitForChild("elevator ding")
local que = {
	
}

local part = script.Parent:WaitForChild("ElevatorMovingFloor")

-- Define the start and end positions
local startPos = Vector3.new(-639.23, 38.56, -212.49)
local endPos = Vector3.new(-639.23, 81.14, -212.49)

-- Define the duration of the tween in seconds
local tweenDuration = 5

-- Get the TweenService
local TweenService = game:GetService("TweenService")

-- Create a new tween
local tweenInfo = TweenInfo.new(tweenDuration)
local tween = TweenService:Create(part, tweenInfo, {Position = endPos})

-- Start the tween


local lowerButtonCall = main:WaitForChild("CallButtonsLower").Button
local upperButtonCall = main:WaitForChild("CallButtonsUpper").Button

local lowerDoors = main:WaitForChild("ElevatorDoorsLower")
local upperDoors = main:WaitForChild("ElevatorDoorsUpper")

local panelLowerButton = main:WaitForChild("ElevatorPanelFloor1")["2"].Button
local panelUpperButton = main:WaitForChild("ElevatorPanelFloor2")["1"].Button



lowerDoors.Parent = nil
lowerButtonCall.ClickDetector.MouseClick:Connect(function()
	print("lower call button")
	local tweenInfo = TweenInfo.new(tweenDuration)
	local tween = TweenService:Create(part, tweenInfo, {Position = startPos})

	-- Start the tween
	if inRoute == false and whichFloor ~= "lower" then
		inRoute = true
		tween:Play()
		upperDoors.Parent = workspace
	end
	
	
	
	
	tween.Completed:Connect(function()
		inRoute = false
		whichFloor = "lower"
		lowerDoors.Parent = nil
		elevatorDingSound:Play()
	end)
end)

upperButtonCall.ClickDetector.MouseClick:Connect(function()
	print("upper call button")
	local tweenInfo = TweenInfo.new(tweenDuration)
	local tween = TweenService:Create(part, tweenInfo, {Position = endPos})

	-- Start the tween
	if inRoute == false and whichFloor ~= "upper" then
		inRoute = true
		tween:Play()
		lowerDoors.Parent = workspace
	end




	tween.Completed:Connect(function()
		inRoute = false
		whichFloor = "upper"
		upperDoors.Parent = nil
		elevatorDingSound:Play()
	end)
end)



panelLowerButton.ClickDetector.MouseClick:Connect(function()
	print("Going to upper floor")
	local tweenInfo = TweenInfo.new(tweenDuration)
	local tween = TweenService:Create(part, tweenInfo, {Position = endPos})

	-- Start the tween
	if inRoute == false and whichFloor ~= "upper" then
		inRoute = true
		tween:Play()
		lowerDoors.Parent = workspace
	end




	tween.Completed:Connect(function()
		inRoute = false
		whichFloor = "upper"
		upperDoors.Parent = nil
		elevatorDingSound:Play()
	end)
end)

panelUpperButton.ClickDetector.MouseClick:Connect(function()
	print("Going to lower floor")
	local tweenInfo = TweenInfo.new(tweenDuration)
	local tween = TweenService:Create(part, tweenInfo, {Position = startPos})

	-- Start the tween
	if inRoute == false and whichFloor ~= "lower" then
		inRoute = true
		tween:Play()
		upperDoors.Parent = workspace
	end




	tween.Completed:Connect(function()
		inRoute = false
		whichFloor = "lower"
		lowerDoors.Parent = nil
		elevatorDingSound:Play()
	end)
end)
2 Likes

That’s just latency…

Or you could just handle the other player’s character on the itself (client), which is much more difficult.

So how do I solve this? Cause it looks terrible. How do other games make elevators?

use physics constraints over tweens.

tweens are not synced client to client, it doesn’t respect physics and platform needs to be anchored.

if you want to keep using tweens try to set the humanoid platform stand property when on top of moving platforms.

The platform is anchored.
//////////////////

anyone have any ideas?
///////////////////////////////////////////////

Tweens work by directly modifying the CFrame or Position of objects without interacting with the physics engine, which can cause other players or objects to desync or not behave correctly when they are in a tweened object (like an elevator). Since tweens bypass the physics system, players inside the elevator might not properly “stick” to the moving platform, especially for players not in control of the elevator. This results in players sometimes going through the floor or behaving unpredictably. The network ownership of a part determines which player controls the physics of the part.

Potential Solutions

  • Manually set Network Ownership of the elevator part to the Server
part:SetNetworkOwner(nil) -- Set the network ownership to the server
  • Weld Players to the Elevator
local weld = Instance.new("WeldConstraint")
weld.Part0 = player.Character.HumanoidRootPart
weld.Part1 = part -- The moving elevator part
weld.Parent = player.Character.HumanoidRootPart
  • Use Constraints Instead of Tween; constraints interact with Roblox’s physics engine, ensuring players “stick” to the platform naturally.
local BodyPosition = Instance.new("BodyPosition")
BodyPosition.MaxForce = Vector3.new(1e5, 1e5, 1e5) -- Strong enough force
BodyPosition.Position = endPos -- Move to the end position
BodyPosition.Parent = part -- Apply to the elevator part
part:SetNetworkOwner(nil)

Why is the argument nil? What does that do.

Apologies for late response; that makes sure network ownership is set to Server. The default is usually the closest Player or otherwise Server. This keeps it as Server. Network Ownership decides who calculates the physics. A specific player or the Server.